OpenCores
URL https://opencores.org/ocsvn/ao486/ao486/trunk

Subversion Repositories ao486

[/] [ao486/] [trunk/] [ao486_tool/] [src/] [ao486/] [AutogenGenerator.java] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/*
2
 * Copyright (c) 2014, Aleksander Osman
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * * Redistributions of source code must retain the above copyright notice, this
9
 *   list of conditions and the following disclaimer.
10
 *
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 *   this list of conditions and the following disclaimer in the documentation
13
 *   and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
 
27
package ao486;
28
 
29
import java.io.File;
30
import java.io.FileOutputStream;
31
import java.nio.file.Files;
32
import java.util.HashMap;
33
import java.util.HashSet;
34
import java.util.LinkedList;
35
import java.util.Stack;
36
import java.util.regex.Matcher;
37
import java.util.regex.Pattern;
38
 
39
class Condition {
40
    Condition(int index, boolean negation, int level) {
41
        this.negation = negation;
42
        this.index = index;
43
        this.level = level;
44
    }
45
    Condition() {
46
    }
47
    @Override
48
    public Object clone() {
49
        Condition c = new Condition(index, negation, level);
50
        return c;
51
    }
52
    boolean negation;
53
    int     index;
54
    int     level;
55
}
56
 
57
class ConditionPoint {
58
    ConditionPoint(String name, Stack<Condition> stack, String value) throws Exception {
59
        this.name = name;
60
        this.value= value;
61
 
62
        conditions_stack = new Stack<>();
63
        for(int i=0; i<stack.size(); i++) {
64
            conditions_stack.push((Condition)stack.elementAt(i).clone());
65
        }
66
    }
67
    String           name;
68
    String           value;
69
    Stack<Condition> conditions_stack;
70
}
71
 
72
class Model {
73
    void IF(String condition) {
74
 
75
        int level = 0;
76
        if(conditions_stack.empty() == false) {
77
            level = conditions_stack.peek().level + 1;
78
        }
79
 
80
        // find previous
81
        for(int i=0; i<conditions.size(); i++) {
82
            String str = conditions.get(i);
83
 
84
            if(str.equals(condition)) {
85
                conditions_stack.push(new Condition(i, false, level));
86
                return;
87
            }
88
        }
89
        int index = conditions.size();
90
        conditions_stack.push(new Condition(index, false, level));
91
        conditions.add(condition);
92
    }
93
    void ELSE() {
94
        conditions_stack.peek().negation = true;
95
    }
96
    void ELSE_IF(String condition) {
97
        conditions_stack.peek().negation = true;
98
 
99
        int level = conditions_stack.peek().level;
100
 
101
        // find previous
102
        for(int i=0; i<conditions.size(); i++) {
103
            String str = conditions.get(i);
104
 
105
            if(str.equals(condition)) {
106
                conditions_stack.push(new Condition(i, false, level));
107
                return;
108
            }
109
        }
110
        int index = conditions.size();
111
        conditions_stack.push(new Condition(index, false, level));
112
        conditions.add(condition);
113
    }
114
    void ENDIF() {
115
        int level = conditions_stack.peek().level;
116
 
117
        while(conditions_stack.empty() == false && conditions_stack.peek().level == level) conditions_stack.pop();
118
    }
119
    void SET(String wire) throws Exception {
120
        SET(wire, "`TRUE");
121
    }
122
    void SAVE(String register, String value) throws Exception {
123
        saves.add(new ConditionPoint(register, conditions_stack, value));
124
    }
125
    void SET(String wire, String value) throws Exception {
126
        sets.add(new ConditionPoint(wire, conditions_stack, value));
127
    }
128
 
129
    void NO_ALWAYS_BLOCK(String register) throws Exception {
130
        no_always_block.add(register);
131
 
132
        //add register if signal also in wires
133
        if(wires.containsKey(register + "_to_reg")) {
134
            int size_w = wires.get(register + "_to_reg");
135
 
136
            if(registers.containsKey(register)) {
137
                int size_r = registers.get(register);
138
                if(size_w != size_r) throw new Exception("");
139
            }
140
            else {
141
                registers.put(register, size_w);
142
            }
143
        }
144
    }
145
 
146
    String convert_expression(String expression) {
147
        return expression;
148
    }
149
 
150
    String template(String string, Object... args) {
151
        for(int i=0; i<args.length; i++) {
152
            string = string.replaceAll("#" + (i+1), args[i].toString());
153
        }
154
        return string;
155
    }
156
 
157
    String generate() throws Exception {
158
        StringBuilder build = new StringBuilder();
159
 
160
        build.append("//======================================================== conditions\n");
161
        for(int i=0; i<conditions.size(); i++) {
162
            String condition = conditions.get(i);
163
 
164
            condition = convert_expression(condition);
165
 
166
            build.append(template("wire cond_#1 = #2;\n", i, condition));
167
        }
168
 
169
        build.append("//======================================================== saves\n");
170
        HashMap<String, StringBuilder> to_regs_map = new HashMap<>();
171
 
172
        for(ConditionPoint point : saves) {
173
 
174
            String condition = "";
175
            for(Condition cond : point.conditions_stack) {
176
                if(condition.length() > 0) condition += " && ";
177
                condition += ((cond.negation)? "~" : "") + ("cond_" + cond.index);
178
            }
179
 
180
            if(condition.length() == 0) throw new Exception("Invalid SAVE(): no condition.");
181
 
182
            String name  = convert_expression(point.name);
183
            String value = convert_expression(point.value);
184
 
185
            StringBuilder builder = to_regs_map.get(name);
186
            if(builder == null) {
187
                builder = new StringBuilder();
188
                to_regs_map.put(name, builder);
189
            }
190
 
191
            builder.append(template("    (#1)? (#2) :\n", condition,value));
192
        }
193
 
194
        for(String name : to_regs_map.keySet()) {
195
 
196
            if(registers.containsKey(name) == false) throw new Exception("Save to unknown register: " + name);
197
            int size = registers.get(name);
198
 
199
            String header = "wire #1";
200
            if(wires.containsKey(name + "_to_reg")) header = "assign";
201
 
202
            build.append(template(header + " #2_to_reg =\n", (size > 1)? "[" + (size-1) + ":0]" : "", name));
203
            build.append(to_regs_map.get(name));
204
            build.append(template("    #1;\n", name));
205
 
206
        }
207
 
208
        build.append("//======================================================== always\n");
209
 
210
        for(String name : to_regs_map.keySet()) {
211
 
212
            if(registers.containsKey(name) == false) throw new Exception("Save to unknown register: " + name);
213
            int size = registers.get(name);
214
 
215
            if(no_always_block.contains(name)) continue;
216
 
217
            build.append(template("always @(posedge clk or negedge rst_n) begin\n"));
218
            build.append(template("    if(rst_n == 1'b0) #1 <= #2'd0;\n", name, "" + size));
219
            build.append(template("    else              #1 <= #1_to_reg;\n", name));
220
            build.append(template("end\n"));
221
        }
222
 
223
 
224
        build.append("//======================================================== sets\n");
225
        HashMap<String, StringBuilder> to_wires_map = new HashMap<>();
226
 
227
        for(ConditionPoint point : sets) {
228
 
229
            String condition = "";
230
            for(Condition cond : point.conditions_stack) {
231
                if(condition.length() > 0) condition += " && ";
232
                condition += ((cond.negation)? "~" : "") + ("cond_" + cond.index);
233
            }
234
 
235
            if(condition.length() == 0) throw new Exception("Invalid SET(): no condition.");
236
 
237
            String name  = convert_expression(point.name);
238
            String value = convert_expression(point.value);
239
 
240
            StringBuilder builder = to_wires_map.get(name);
241
            if(builder == null) {
242
                builder = new StringBuilder();
243
                to_wires_map.put(name, builder);
244
            }
245
            builder.append(template("    (#1)? (#2) :\n", condition,value));
246
        }
247
 
248
        for(String name : to_wires_map.keySet()) {
249
 
250
            if(wires.containsKey(name) == false) throw new Exception("Set to unknown wire: " + name);
251
            int size = wires.get(name);
252
 
253
            build.append(template("assign #1 =\n", name));
254
 
255
            build.append(to_wires_map.get(name));
256
            build.append(template("    #1'd0;\n", "" + size));
257
        }
258
 
259
        return build.toString();
260
    }
261
 
262
 
263
    Stack<Condition>            conditions_stack= new Stack<>();
264
    LinkedList<String>          conditions      = new LinkedList<>();
265
 
266
    LinkedList<ConditionPoint>  sets            = new LinkedList<>();
267
    LinkedList<ConditionPoint>  saves           = new LinkedList<>();
268
 
269
    HashMap<String, Integer>    registers       = new HashMap<>();
270
    HashMap<String, Integer>    wires           = new HashMap<>();
271
 
272
    HashSet<String>             no_always_block = new HashSet<>();
273
}
274
 
275
public class AutogenGenerator {
276
 
277
    static String strip(String string, String pattern) {
278
        Pattern p = Pattern.compile(pattern);
279
        Matcher m = p.matcher(string);
280
 
281
        StringBuffer sb = new StringBuffer();
282
        while (m.find()) {
283
            m.appendReplacement(sb, "");
284
        }
285
        m.appendTail(sb);
286
 
287
        return sb.toString();
288
    }
289
 
290
    static void findRegsAndWires(String source, Model model) {
291
 
292
        // strip comments
293
        source = strip(source, "//[^\\n]*");
294
 
295
        // regs
296
        Matcher reg_single = Pattern.compile("reg\\s+(\\w+)\\s*;").matcher(source);
297
        while(reg_single.find()) model.registers.put(reg_single.group(1), 1);
298
 
299
        Matcher reg_vector = Pattern.compile("reg\\s+\\[(\\d+)\\s*:\\s*0\\s*\\]\\s*(\\w+)\\s*;").matcher(source);
300
        while(reg_vector.find()) model.registers.put(reg_vector.group(2), Integer.parseInt(reg_vector.group(1))+1);
301
 
302
        Matcher out_reg_single = Pattern.compile("output\\s+reg\\s+(\\w+)\\s*[,\\)\\s]").matcher(source);
303
        while(out_reg_single.find()) model.registers.put(out_reg_single.group(1), 1);
304
 
305
        Matcher out_reg_vector = Pattern.compile("output\\s+reg\\s+\\[(\\d+)\\s*:\\s*0\\s*\\]\\s*(\\w+)\\s*[,\\)\\s]").matcher(source);
306
        while(out_reg_vector.find()) model.registers.put(out_reg_vector.group(2), Integer.parseInt(out_reg_vector.group(1))+1);
307
 
308
        //wires
309
        Matcher wire_single = Pattern.compile("wire\\s+(\\w+)\\s*;").matcher(source);
310
        while(wire_single.find()) model.wires.put(wire_single.group(1), 1);
311
 
312
        Matcher wire_vector = Pattern.compile("wire\\s+\\[(\\d+)\\s*:\\s*0\\s*\\]\\s*(\\w+)\\s*;").matcher(source);
313
        while(wire_vector.find()) model.wires.put(wire_vector.group(2), Integer.parseInt(wire_vector.group(1))+1);
314
 
315
        Matcher out_wire_single = Pattern.compile("output\\s+(\\w+)\\s*[,\\)\\s]").matcher(source);
316
        while(out_wire_single.find()) model.wires.put(out_wire_single.group(1), 1);
317
 
318
        Matcher out_wire_vector = Pattern.compile("output\\s+\\[(\\d+)\\s*:\\s*0\\s*\\]\\s*(\\w+)\\s*[,\\)\\s]").matcher(source);
319
        while(out_wire_vector.find()) model.wires.put(out_wire_vector.group(2), Integer.parseInt(out_wire_vector.group(1))+1);
320
 
321
    }
322
 
323
    static void parseScript(String script, Model model) throws Exception {
324
 
325
        // strip comments
326
        script = strip(script, "//[^\\n]*");
327
 
328
        // strip start and end whitespace
329
        script = script.trim();
330
 
331
        Pattern if_pattern       = Pattern.compile("(?s)^\\s*IF\\s*\\((.*?)\\)\\s*;");
332
        Pattern set_true_pattern = Pattern.compile("^\\s*SET\\s*\\((.*?)\\)\\s*;");
333
        Pattern set_pattern      = Pattern.compile("(?s)^\\s*SET\\s*\\(([^,\\)]*),(.*?)\\)\\s*;");
334
        Pattern save_pattern     = Pattern.compile("(?s)^\\s*SAVE\\s*\\(([^,\\)]*),(.*?)\\)\\s*;");
335
        Pattern endif_pattern    = Pattern.compile("^\\s*ENDIF\\s*\\(\\s*\\)\\s*;");
336
        Pattern else_pattern     = Pattern.compile("^\\s*ELSE\\s*\\(\\s*\\)\\s*;");
337
        Pattern elseif_pattern   = Pattern.compile("(?s)^\\s*ELSE_IF\\s*\\((.*?)\\)\\s*;");
338
        Pattern no_always_pattern= Pattern.compile("^\\s*NO_ALWAYS_BLOCK\\s*\\((.*?)\\)\\s*;");
339
 
340
        while(true) {
341
            Matcher if_matcher       = if_pattern.matcher(script);
342
            Matcher set_true_matcher = set_true_pattern.matcher(script);
343
            Matcher set_matcher      = set_pattern.matcher(script);
344
            Matcher save_matcher     = save_pattern.matcher(script);
345
            Matcher endif_matcher    = endif_pattern.matcher(script);
346
            Matcher else_matcher     = else_pattern.matcher(script);
347
            Matcher elseif_matcher   = elseif_pattern.matcher(script);
348
            Matcher no_always_matcher= no_always_pattern.matcher(script);
349
 
350
            if(if_matcher.find()) {
351
                model.IF(if_matcher.group(1));
352
                script = script.substring(if_matcher.end());
353
            }
354
            else if(set_matcher.find()) {
355
                model.SET(set_matcher.group(1), set_matcher.group(2));
356
                script = script.substring(set_matcher.end());
357
            }
358
            else if(set_true_matcher.find()) {
359
                model.SET(set_true_matcher.group(1));
360
                script = script.substring(set_true_matcher.end());
361
            }
362
            else if(save_matcher.find()) {
363
                model.SAVE(save_matcher.group(1), save_matcher.group(2));
364
                script = script.substring(save_matcher.end());
365
            }
366
            else if(endif_matcher.find()) {
367
                model.ENDIF();
368
                script = script.substring(endif_matcher.end());
369
            }
370
            else if(else_matcher.find()) {
371
                model.ELSE();
372
                script = script.substring(else_matcher.end());
373
            }
374
            else if(elseif_matcher.find()) {
375
                model.ELSE_IF(elseif_matcher.group(1));
376
                script = script.substring(elseif_matcher.end());
377
            }
378
            else if(no_always_matcher.find()) {
379
                model.NO_ALWAYS_BLOCK(no_always_matcher.group(1));
380
                script = script.substring(no_always_matcher.end());
381
            }
382
            else break;
383
        }
384
        if(model.conditions_stack.empty() == false) throw new Exception("Condition stack not empty: " +
385
                model.conditions.get(model.conditions_stack.peek().index));
386
 
387
        if(script.length() > 0) throw new Exception("Left not empty: " + script);
388
    }
389
 
390
    static void process_file(File file) throws Exception {
391
        byte file_bytes[] = Files.readAllBytes(file.toPath());
392
        String file_string = new String(file_bytes);
393
 
394
        if(file_string.indexOf("//PARSED_COMMENTS") == -1) return;
395
 
396
        System.out.println("Processing file: " + file);
397
 
398
        String start_string = "/*******************************************************************************SCRIPT";
399
        String end_string   = "*/";
400
 
401
        int index = 0;
402
 
403
        Model model = new Model();
404
 
405
        findRegsAndWires(file_string, model);
406
 
407
        while(true) {
408
            index = file_string.indexOf(start_string, index);
409
            if(index == -1) break;
410
 
411
            index += start_string.length();
412
 
413
            int end = file_string.indexOf(end_string, index);
414
            if(end == -1) throw new Exception("Invalid script: end string not found.");
415
 
416
            String script = file_string.substring(index, end);
417
            parseScript(script, model);
418
        }
419
        // expand macros
420
        if(file.getName().toLowerCase().equals("decode_commands.v")) {
421
            String script = Commands.decode.toString();
422
 
423
            parseScript(script, model);
424
        }
425
        if(file.getName().toLowerCase().equals("microcode_commands.v")) {
426
            String script = Commands.microcode.toString();
427
 
428
            //System.out.println("microcode:\n" + script);
429
            parseScript(script, model);
430
        }
431
        if(file.getName().toLowerCase().equals("read_commands.v")) {
432
            String script = Commands.read.toString();
433
 
434
            //System.out.println("microcode:\n" + script);
435
            parseScript(script, model);
436
        }
437
        if(file.getName().toLowerCase().equals("execute_commands.v")) {
438
            String script = Commands.execute.toString();
439
 
440
            //System.out.println("execute:\n" + script);
441
            parseScript(script, model);
442
        }
443
        if(file.getName().toLowerCase().equals("write_commands.v")) {
444
            String script = Commands.write.toString();
445
 
446
            //System.out.println("execute:\n" + script);
447
            parseScript(script, model);
448
        }
449
 
450
        // get old contents
451
        File autogen_file = new File(autogen_dir.getCanonicalPath() + "/" + file.getName());
452
 
453
        String old_contents = "";
454
        if(autogen_file.exists()) {
455
            old_contents = new String(Files.readAllBytes(autogen_file.toPath()));
456
        }
457
 
458
        // generate new contents
459
        String new_contents = model.generate();
460
 
461
        if(file.getName().toLowerCase().equals("read_commands.v")) {
462
            new_contents = Commands.read_local + new_contents;
463
        }
464
        if(file.getName().toLowerCase().equals("execute_commands.v")) {
465
            new_contents = Commands.execute_local + new_contents;
466
        }
467
        if(file.getName().toLowerCase().equals("write_commands.v")) {
468
            new_contents = Commands.write_local + new_contents;
469
        }
470
 
471
        if(new_contents.equals(old_contents) == false) {
472
            FileOutputStream out = new FileOutputStream(autogen_file);
473
            out.write(new_contents.getBytes());
474
            out.close();
475
        }
476
    }
477
 
478
    static void recurrent(File directory) throws Exception {
479
        for(File file : directory.listFiles()) {
480
            if(file.isDirectory()) {
481
                recurrent(file);
482
                continue;
483
            }
484
 
485
            // skip autogen files
486
            if(file.getCanonicalPath().indexOf("autogen") != -1) continue;
487
 
488
            process_file(file);
489
        }
490
    }
491
 
492
    static void process_defines() throws Exception {
493
        File defines_file = new File(autogen_dir.getCanonicalPath() + "/" + "defines.v");
494
 
495
        String old_contents = "";
496
        if(defines_file.exists()) {
497
            old_contents = new String(Files.readAllBytes(defines_file.toPath()));
498
        }
499
 
500
        StringBuilder new_contents = new StringBuilder();
501
        for(String key : Commands.defines.keySet()) {
502
            new_contents.append("`define " + key + " " + Commands.defines.get(key) + "\n");
503
        }
504
 
505
        if(new_contents.toString().equals(old_contents) == false) {
506
            FileOutputStream out = new FileOutputStream(defines_file);
507
            out.write(new_contents.toString().getBytes());
508
            out.close();
509
        }
510
    }
511
 
512
    public static void main(String args[]) throws Exception {
513
 
514
        File rtl_dir = new File("./../rtl/ao486");
515
        File cmd_dir = new File("./../rtl/ao486/commands");
516
        autogen_dir = new File("./../rtl/ao486/autogen");
517
 
518
        Commands.read_command_files(cmd_dir);
519
 
520
        process_defines();
521
 
522
        recurrent(rtl_dir);
523
    }
524
 
525
    static File autogen_dir;
526
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.