diff options
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | frontends/ast/simplify.cc | 16 | ||||
-rw-r--r-- | frontends/verilog/verilog_parser.y | 4 | ||||
-rw-r--r-- | manual/CHAPTER_Overview.tex | 7 | ||||
-rw-r--r-- | misc/py_wrap_generator.py | 40 | ||||
-rw-r--r-- | passes/techmap/abc9_exe.cc | 2 | ||||
-rw-r--r-- | techlibs/xilinx/abc9_map.v | 80 | ||||
-rw-r--r-- | tests/memfile/.gitignore | 1 | ||||
-rw-r--r-- | tests/memfile/content1.dat | 64 | ||||
-rw-r--r-- | tests/memfile/memory.v | 23 | ||||
-rwxr-xr-x | tests/memfile/run-test.sh | 49 | ||||
-rw-r--r-- | tests/various/bug1614.ys | 5 |
13 files changed, 245 insertions, 48 deletions
@@ -60,6 +60,7 @@ Yosys 0.9 .. Yosys 0.9-dev - Added "scratchpad" pass - Added "abc9 -dff" - Added "synth_xilinx -dff" + - Improved support of $readmem[hb] Memory Content File inclusion - Added "opt_lut_ins" pass Yosys 0.8 .. Yosys 0.9 @@ -728,6 +728,7 @@ test: $(TARGETS) $(EXTRA_TARGETS) +cd tests/arch/anlogic && bash run-test.sh $(SEEDOPT) +cd tests/arch/gowin && bash run-test.sh $(SEEDOPT) +cd tests/rpc && bash run-test.sh + +cd tests/memfile && bash run-test.sh @echo "" @echo " Passed \"make test\"." @echo "" diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 8855d9954..fe0412699 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2903,9 +2903,19 @@ AstNode *AstNode::readmem(bool is_readmemh, std::string mem_filename, AstNode *m std::ifstream f; f.open(mem_filename.c_str()); - yosys_input_files.insert(mem_filename); - - if (f.fail()) + if (f.fail()) { +#ifdef _WIN32 + char slash = '\\'; +#else + char slash = '/'; +#endif + std::string path = filename.substr(0, filename.find_last_of(slash)+1); + f.open(path + mem_filename.c_str()); + yosys_input_files.insert(path + mem_filename); + } else { + yosys_input_files.insert(mem_filename); + } + if (f.fail() || GetSize(mem_filename) == 0) log_file_error(filename, linenum, "Can not open file `%s` for %s.\n", mem_filename.c_str(), str.c_str()); log_assert(GetSize(memory->children) == 2 && memory->children[1]->type == AST_RANGE && memory->children[1]->range_valid); diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 2c7304cc4..8840cf4e8 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -476,7 +476,7 @@ wire_type: astbuf3 = new AstNode(AST_WIRE); current_wire_rand = false; current_wire_const = false; - } wire_type_token_list delay { + } wire_type_token_list { $$ = astbuf3; }; @@ -1240,7 +1240,7 @@ wire_decl: } if (astbuf2 && astbuf2->children.size() != 2) frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]"); - } wire_name_list { + } delay wire_name_list { delete astbuf1; if (astbuf2 != NULL) delete astbuf2; diff --git a/manual/CHAPTER_Overview.tex b/manual/CHAPTER_Overview.tex index 3009bf2c0..be37d8d39 100644 --- a/manual/CHAPTER_Overview.tex +++ b/manual/CHAPTER_Overview.tex @@ -234,6 +234,8 @@ An RTLIL::Wire object has the following properties: \item The wire name \item A list of attributes \item A width (buses are just wires with a width > 1) +\item Bus direction (MSB to LSB or vice versa) +\item Lowest valid bit index (LSB or MSB depending on bus direction) \item If the wire is a port: port number and direction (input/output/inout) \end{itemize} @@ -246,6 +248,11 @@ This makes some aspects of RTLIL more complex but enables Yosys to be used for coarse grain synthesis where the cells of the target architecture operate on entire signal vectors instead of single bit wires. +In Verilog and VHDL, busses may have arbitrary bounds, and LSB can have either +the lowest or the highest bit index. In RTLIL, bit 0 always corresponds to LSB; +however, information from the HDL frontend is preserved so that the bus will be +correctly indexed in error messages, backend output, constraint files, etc. + An RTLIL::Cell object has the following properties: \begin{itemize} diff --git a/misc/py_wrap_generator.py b/misc/py_wrap_generator.py index 9b4e644c0..fac5b48a4 100644 --- a/misc/py_wrap_generator.py +++ b/misc/py_wrap_generator.py @@ -721,6 +721,7 @@ class WClass: name = None namespace = None link_type = None + base_class = None id_ = None string_id = None hash_id = None @@ -732,6 +733,7 @@ class WClass: def __init__(self, name, link_type, id_, string_id = None, hash_id = None, needs_clone = False): self.name = name self.namespace = None + self.base_class = None self.link_type = link_type self.id_ = id_ self.string_id = string_id @@ -804,6 +806,8 @@ class WClass: for con in self.found_constrs: text += con.gen_decl() + if self.base_class is not None: + text += "\n\t\tvirtual ~" + self.name + "() { };" for var in self.found_vars: text += var.gen_decl() for fun in self.found_funs: @@ -908,15 +912,19 @@ class WClass: def gen_boost_py(self): body = self.gen_boost_py_body() + base_info = "" + if self.base_class is not None: + base_info = ", bases<" + (self.base_class.name) + ">" + if self.link_type == link_types.derive: - text = "\n\t\tclass_<" + self.name + ">(\"Cpp" + self.name + "\"" + text = "\n\t\tclass_<" + self.name + base_info + ">(\"Cpp" + self.name + "\"" text += body text += "\n\t\tclass_<" + self.name text += "Wrap, boost::noncopyable" text += ">(\"" + self.name + "\"" text += body else: - text = "\n\t\tclass_<" + self.name + ">(\"" + self.name + "\"" + text = "\n\t\tclass_<" + self.name + base_info + ">(\"" + self.name + "\"" text += body return text @@ -1971,9 +1979,21 @@ def parse_header(source): for namespace in impl_namespaces: complete_namespace += "::" + namespace debug("\tFound " + struct_name + " in " + complete_namespace,2) + + base_class_name = None + if len(ugly_line.split(" : ")) > 1: # class is derived + deriv_str = ugly_line.split(" : ")[1] + if len(deriv_str.split("::")) > 1: # namespace of base class is given + base_class_name = deriv_str.split("::", 1)[1] + else: + base_class_name = deriv_str.split(" ")[0] + debug("\t " + struct_name + " is derived from " + base_class_name,2) + base_class = class_by_name(base_class_name) + class_ = (class_by_name(struct_name), ugly_line.count("{"))#calc_ident(line)) if struct_name in classnames: class_[0].namespace = complete_namespace + class_[0].base_class = base_class i += 1 continue @@ -2142,6 +2162,21 @@ def expand_functions(): new_funs.extend(expand_function(fun)) class_.found_funs = new_funs +def inherit_members(): + for source in sources: + for class_ in source.classes: + if class_.base_class: + base_funs = copy.deepcopy(class_.base_class.found_funs) + for fun in base_funs: + fun.member_of = class_ + fun.namespace = class_.namespace + base_vars = copy.deepcopy(class_.base_class.found_vars) + for var in base_vars: + var.member_of = class_ + var.namespace = class_.namespace + class_.found_funs.extend(base_funs) + class_.found_vars.extend(base_vars) + def clean_duplicates(): for source in sources: for class_ in source.classes: @@ -2178,6 +2213,7 @@ def gen_wrappers(filename, debug_level_ = 0): parse_header(source) expand_functions() + inherit_members() clean_duplicates() import shutil diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc index d3db0065c..898285c69 100644 --- a/passes/techmap/abc9_exe.cc +++ b/passes/techmap/abc9_exe.cc @@ -362,7 +362,7 @@ struct Abc9ExePass : public Pass { } void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE { - log_header(design, "Executing ABC9_MAP pass (technology mapping using ABC9).\n"); + log_header(design, "Executing ABC9_EXE pass (technology mapping using ABC9).\n"); #ifdef ABCEXTERNAL std::string exe_file = ABCEXTERNAL; diff --git a/techlibs/xilinx/abc9_map.v b/techlibs/xilinx/abc9_map.v index 7dc027176..539fa4547 100644 --- a/techlibs/xilinx/abc9_map.v +++ b/techlibs/xilinx/abc9_map.v @@ -215,11 +215,11 @@ module FDCE (output Q, (* techmap_autopurge *) input C, CE, D, CLR); .IS_PRE_INVERTED(IS_CLR_INVERTED) ) _TECHMAP_REPLACE_ ( .D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC1 below + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC1 below ); // Since this is an async flop, async behaviour is dealt with here $__ABC9_ASYNC1 abc_async (.A($QQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); @@ -233,11 +233,11 @@ module FDCE (output Q, (* techmap_autopurge *) input C, CE, D, CLR); .IS_CLR_INVERTED(IS_CLR_INVERTED) ) _TECHMAP_REPLACE_ ( .D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC0 below + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC0 below ); // Since this is an async flop, async behaviour is dealt with here $__ABC9_ASYNC0 abc_async (.A($QQ), .S(CLR ^ IS_CLR_INVERTED), .Y(QQ)); @@ -258,11 +258,11 @@ module FDCE_1 (output Q, (* techmap_autopurge *) input C, CE, D, CLR); .INIT(1'b0) ) _TECHMAP_REPLACE_ ( .D(~D), .Q($Q), .C(C), .CE(CE), .PRE(CLR) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC1 below + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC1 below ); $__ABC9_ASYNC1 abc_async (.A($QQ), .S(CLR), .Y(QQ)); end @@ -272,11 +272,11 @@ module FDCE_1 (output Q, (* techmap_autopurge *) input C, CE, D, CLR); .INIT(1'b0) ) _TECHMAP_REPLACE_ ( .D(D), .Q($Q), .C(C), .CE(CE), .CLR(CLR) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC0 below + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC0 below ); $__ABC9_ASYNC0 abc_async (.A($QQ), .S(CLR), .Y(QQ)); end endgenerate @@ -303,11 +303,11 @@ module FDPE (output Q, (* techmap_autopurge *) input C, CE, D, PRE); .IS_CLR_INVERTED(IS_PRE_INVERTED), ) _TECHMAP_REPLACE_ ( .D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC0 below + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC0 below ); $__ABC9_ASYNC0 abc_async (.A($QQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); end @@ -320,11 +320,11 @@ module FDPE (output Q, (* techmap_autopurge *) input C, CE, D, PRE); .IS_PRE_INVERTED(IS_PRE_INVERTED), ) _TECHMAP_REPLACE_ ( .D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC1 below + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC1 below ); $__ABC9_ASYNC1 abc_async (.A($QQ), .S(PRE ^ IS_PRE_INVERTED), .Y(QQ)); end endgenerate @@ -344,11 +344,11 @@ module FDPE_1 (output Q, (* techmap_autopurge *) input C, CE, D, PRE); .INIT(1'b0) ) _TECHMAP_REPLACE_ ( .D(~D), .Q($Q), .C(C), .CE(CE), .CLR(PRE) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC0 below + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC0 below ); $__ABC9_ASYNC0 abc_async (.A($QQ), .S(PRE), .Y(QQ)); end @@ -358,11 +358,11 @@ module FDPE_1 (output Q, (* techmap_autopurge *) input C, CE, D, PRE); .INIT(1'b0) ) _TECHMAP_REPLACE_ ( .D(D), .Q($Q), .C(C), .CE(CE), .PRE(PRE) - // ^^^ Note that async - // control is not directly - // supported by abc9 but its - // behaviour is captured by - // $__ABC9_ASYNC1 below + // ^^^ Note that async + // control is not directly + // supported by abc9 but its + // behaviour is captured by + // $__ABC9_ASYNC1 below ); $__ABC9_ASYNC1 abc_async (.A($QQ), .S(PRE), .Y(QQ)); end endgenerate diff --git a/tests/memfile/.gitignore b/tests/memfile/.gitignore new file mode 100644 index 000000000..61b0d4264 --- /dev/null +++ b/tests/memfile/.gitignore @@ -0,0 +1 @@ +temp* diff --git a/tests/memfile/content1.dat b/tests/memfile/content1.dat new file mode 100644 index 000000000..4d1c67c26 --- /dev/null +++ b/tests/memfile/content1.dat @@ -0,0 +1,64 @@ +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 +00001111000000001111111100000000 diff --git a/tests/memfile/memory.v b/tests/memfile/memory.v new file mode 100644 index 000000000..57106eae8 --- /dev/null +++ b/tests/memfile/memory.v @@ -0,0 +1,23 @@ +// A memory initialized with an external file + +module memory ( + input clk_i, + input we_i, + input [5:0] addr_i, + input [31:0] data_i, + output reg [31:0] data_o +); + +parameter MEMFILE = ""; + +reg [31:0] mem [0:63]; + +initial $readmemb(MEMFILE,mem); + +always @(posedge clk_i) begin + if (we_i) + mem[addr_i] <= data_i; + data_o <= mem[addr_i]; +end + +endmodule diff --git a/tests/memfile/run-test.sh b/tests/memfile/run-test.sh new file mode 100755 index 000000000..e43ddd093 --- /dev/null +++ b/tests/memfile/run-test.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +set -e + +mkdir -p temp +cp content1.dat temp/content2.dat + +cd .. + +echo "Running from the parent directory with content1.dat" +../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"content1.dat\" memory" +echo "Running from the parent directory with temp/content2.dat" +../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" +echo "Running from the parent directory with memfile/temp/content2.dat" +../yosys -qp "read_verilog -defer memfile/memory.v; chparam -set MEMFILE \"memfile/temp/content2.dat\" memory" + +cd memfile + +echo "Running from the same directory with content1.dat" +../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content1.dat\" memory" +echo "Running from the same directory with temp/content2.dat" +../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" + +cd temp + +echo "Running from a child directory with content1.dat" +../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"content1.dat\" memory" +echo "Running from a child directory with temp/content2.dat" +../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" +echo "Running from a child directory with content2.dat" +../../../yosys -qp "read_verilog -defer ../memory.v; chparam -set MEMFILE \"temp/content2.dat\" memory" + +cd .. + +echo "Checking a failure when zero length filename is provided" +if ../../yosys -qp "read_verilog memory.v"; then + echo "The execution should fail but it didn't happen, which is WRONG." + exit 1 +else + echo "Execution failed, which is OK." +fi + +echo "Checking a failure when not existing filename is provided" +if ../../yosys -qp "read_verilog -defer memory.v; chparam -set MEMFILE \"content3.dat\" memory"; then + echo "The execution should fail but it didn't happen, which is WRONG." + exit 1 +else + echo "Execution failed, which is OK." +fi diff --git a/tests/various/bug1614.ys b/tests/various/bug1614.ys new file mode 100644 index 000000000..6fbe84a4c --- /dev/null +++ b/tests/various/bug1614.ys @@ -0,0 +1,5 @@ +read_verilog <<EOT +module testcase; + wire [3:0] #1 a = 4'b0000; +endmodule +EOT |