diff --git a/sv-parser-parser/src/behavioral_statements/looping_statements.rs b/sv-parser-parser/src/behavioral_statements/looping_statements.rs index 69c1598..c2e7e91 100644 --- a/sv-parser-parser/src/behavioral_statements/looping_statements.rs +++ b/sv-parser-parser/src/behavioral_statements/looping_statements.rs @@ -51,9 +51,9 @@ pub(crate) fn loop_statement_for(s: Span) -> IResult { let (s, a) = keyword("for")(s)?; let (s, b) = paren(tuple(( opt(for_initialization), - symbol(":"), + symbol(";"), opt(expression), - symbol(":"), + symbol(";"), opt(for_step), )))(s)?; let (s, c) = statement_or_null(s)?; diff --git a/sv-parser-parser/src/behavioral_statements/timing_control_statements.rs b/sv-parser-parser/src/behavioral_statements/timing_control_statements.rs index b1477f4..4a5ac35 100644 --- a/sv-parser-parser/src/behavioral_statements/timing_control_statements.rs +++ b/sv-parser-parser/src/behavioral_statements/timing_control_statements.rs @@ -121,10 +121,10 @@ pub(crate) fn event_control_sequence_identifier(s: Span) -> IResult IResult { alt(( - event_expression_expression, - event_expression_sequence, event_expression_or, event_expression_comma, + event_expression_expression, + event_expression_sequence, event_expression_paren, ))(s) } diff --git a/sv-parser-parser/src/declarations/net_and_variable_types.rs b/sv-parser-parser/src/declarations/net_and_variable_types.rs index d0d9911..f0ca335 100644 --- a/sv-parser-parser/src/declarations/net_and_variable_types.rs +++ b/sv-parser-parser/src/declarations/net_and_variable_types.rs @@ -27,8 +27,10 @@ pub(crate) fn data_type(s: Span) -> IResult { map(keyword("string"), |x| DataType::String(Box::new(x))), map(keyword("chandle"), |x| DataType::Chandle(Box::new(x))), data_type_virtual, + map(terminated(class_type, peek(not(packed_dimension))), |x| { + DataType::ClassType(Box::new(x)) + }), data_type_type, - map(class_type, |x| DataType::ClassType(Box::new(x))), map(keyword("event"), |x| DataType::Chandle(Box::new(x))), map(ps_covergroup_identifier, |x| { DataType::PsCovergroupIdentifier(Box::new(x)) diff --git a/sv-parser-parser/src/expressions/primaries.rs b/sv-parser-parser/src/expressions/primaries.rs index 2698f5f..9952df2 100644 --- a/sv-parser-parser/src/expressions/primaries.rs +++ b/sv-parser-parser/src/expressions/primaries.rs @@ -151,6 +151,7 @@ pub(crate) fn primary(s: Span) -> IResult { Primary::AssignmentPatternExpression(Box::new(x)) }), map(primary_literal, |x| Primary::PrimaryLiteral(Box::new(x))), + map(cast, |x| Primary::Cast(Box::new(x))), terminated(primary_hierarchical, peek(none_of("("))), map(empty_unpacked_array_concatenation, |x| { Primary::EmptyUnpackedArrayConcatenation(Box::new(x)) @@ -162,7 +163,6 @@ pub(crate) fn primary(s: Span) -> IResult { }), map(let_expression, |x| Primary::LetExpression(Box::new(x))), primary_mintypmax_expression, - map(cast, |x| Primary::Cast(Box::new(x))), map(streaming_concatenation, |x| { Primary::StreamingConcatenation(Box::new(x)) }), @@ -319,7 +319,10 @@ pub(crate) fn bit_select(s: Span) -> IResult { #[tracable_parser] pub(crate) fn select(s: Span) -> IResult { let (s, a) = opt(triple( - many0(triple(symbol("."), member_identifier, bit_select)), + many0(terminated( + triple(symbol("."), member_identifier, bit_select), + peek(symbol(".")), + )), symbol("."), member_identifier, ))(s)?; @@ -348,7 +351,10 @@ pub(crate) fn constant_bit_select(s: Span) -> IResult { #[tracable_parser] pub(crate) fn constant_select(s: Span) -> IResult { let (s, a) = opt(triple( - many0(triple(symbol("."), member_identifier, constant_bit_select)), + many0(terminated( + triple(symbol("."), member_identifier, constant_bit_select), + peek(symbol(".")), + )), symbol("."), member_identifier, ))(s)?; diff --git a/sv-parser-parser/src/source_text/library_source_text.rs b/sv-parser-parser/src/source_text/library_source_text.rs index c87337a..8b5b147 100644 --- a/sv-parser-parser/src/source_text/library_source_text.rs +++ b/sv-parser-parser/src/source_text/library_source_text.rs @@ -47,9 +47,19 @@ pub(crate) fn include_statement(s: Span) -> IResult { Ok((s, IncludeStatement { nodes: (a, b, c) })) } -//TODO support non literal path #[tracable_parser] pub(crate) fn file_path_spec(s: Span) -> IResult { - let (s, a) = string_literal(s)?; - Ok((s, FilePathSpec { nodes: (a,) })) + alt(( + map(string_literal, |x| FilePathSpec::Literal(x)), + file_path_spec_non_literal, + ))(s) +} + +#[tracable_parser] +pub(crate) fn file_path_spec_non_literal(s: Span) -> IResult { + let (s, a) = ws(map(is_not(",; "), |x| into_locate(x)))(s)?; + Ok(( + s, + FilePathSpec::NonLiteral(FilePathSpecNonLiteral { nodes: a }), + )) } diff --git a/sv-parser-parser/src/tests.rs b/sv-parser-parser/src/tests.rs index 4181c7b..5f497d5 100644 --- a/sv-parser-parser/src/tests.rs +++ b/sv-parser-parser/src/tests.rs @@ -4,6 +4,7 @@ use crate::*; macro_rules! test { ( $x:expr, $y:expr, $z:pat ) => { + nom_packrat::init!(); let info = SpanInfo::default(); let ret = all_consuming($x)(Span::new_extra($y, info)); if let $z = ret { @@ -141,22 +142,8 @@ fn test_data_type() { ); } -#[test] -fn test_local_parameter_declaration() { - test!( - local_parameter_declaration, - "localparam byte colon1 = \":\" ", - Ok((_, LocalParameterDeclaration::Param(_))) - ); -} - #[test] fn test_parameter_declaration() { - test!( - parameter_declaration, - "parameter logic flag = 1 ", - Ok((_, ParameterDeclaration::Param(_))) - ); test!( parameter_declaration, "parameter e = 25, f = 9 ", @@ -211,288 +198,8 @@ fn test_inout_declaration() { test!(inout_declaration, "inout signed [7:0] a", Ok((_, _))); } -#[test] -fn test_net_type_declaration() { - test!( - net_type_declaration, - "nettype T wT;", - Ok((_, NetTypeDeclaration::DataType(_))) - ); - test!( - net_type_declaration, - "nettype T wTsum with Tsum;", - Ok((_, NetTypeDeclaration::DataType(_))) - ); - test!( - net_type_declaration, - "nettype MyBaseT::T narrowTsum with MyBaseT::Tsum;", - Ok((_, NetTypeDeclaration::DataType(_))) - ); -} - -#[test] -fn test_net_declaration() { - test!( - net_declaration, - "trireg (large) logic #(0,0,0) cap1;", - Ok((_, NetDeclaration::NetType(_))) - ); - test!( - net_declaration, - "wire addressT w1;", - Ok((_, NetDeclaration::NetType(_))) - ); - test!( - net_declaration, - "wire struct packed { logic ecc; logic [7:0] data; } memsig;", - Ok((_, NetDeclaration::NetType(_))) - ); - test!( - net_declaration, - "wire w;", - Ok((_, NetDeclaration::NetType(_))) - ); - test!( - net_declaration, - "wire [15:0] w;", - Ok((_, NetDeclaration::NetType(_))) - ); - test!( - net_declaration, - "interconnect w1;", - Ok((_, NetDeclaration::Interconnect(_))) - ); - test!( - net_declaration, - "interconnect [3:0] w2;", - Ok((_, NetDeclaration::Interconnect(_))) - ); - test!( - net_declaration, - "interconnect [3:0] w3 [1:0];", - Ok((_, NetDeclaration::Interconnect(_))) - ); - test!(net_declaration, "interconnect logic [3:0] w4;", Err(_)); - test!(net_declaration, "interconnect #(1,2,3) w5;", Err(_)); - test!( - net_declaration, - "wand w;", - Ok((_, NetDeclaration::NetType(_))) - ); - test!( - net_declaration, - "tri [15:0] busa;", - Ok((_, NetDeclaration::NetType(_))) - ); - test!( - net_declaration, - "trireg (small) storeit;", - Ok((_, NetDeclaration::NetType(_))) - ); - test!( - net_declaration, - "wire w1, w2;", - Ok((_, NetDeclaration::NetType(_))) - ); - test!( - net_declaration, - "tri1 scalared [63:0] bus64;", - Ok((_, NetDeclaration::NetType(_))) - ); - test!( - net_declaration, - "tri vectored [31:0] data;", - Ok((_, NetDeclaration::NetType(_))) - ); -} - #[test] fn test_data_declaration() { - test!( - data_declaration, - "shortint s1, s2[0:9];", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "var byte my_byte;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "var v;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "var [15:0] vw;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "var enum bit { clear, error } status;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "var reg r;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "int i = 0;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "logic a;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "logic[3:0] v;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "logic signed [3:0] signed_reg;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "logic [-1:4] b;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "logic [4:0] x, y, z;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "int unsigned ui;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "int signed si;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "string myName = default_name;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "byte c = \"A\";", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "bit [10:0] b = \"x41\";", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "bit [1:4][7:0] h = \"hello\" ;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "event done;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "event done_too = done;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "event empty = null;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "typedef int intP;", - Ok((_, DataDeclaration::TypeDeclaration(_))) - ); - test!( - data_declaration, - "intP a, b;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "typedef enum type_identifier;", - Ok((_, DataDeclaration::TypeDeclaration(_))) - ); - test!( - data_declaration, - "typedef struct type_identifier;", - Ok((_, DataDeclaration::TypeDeclaration(_))) - ); - test!( - data_declaration, - "typedef union type_identifier;", - Ok((_, DataDeclaration::TypeDeclaration(_))) - ); - test!( - data_declaration, - "typedef class type_identifier;", - Ok((_, DataDeclaration::TypeDeclaration(_))) - ); - test!( - data_declaration, - "typedef interface class type_identifier;", - Ok((_, DataDeclaration::TypeDeclaration(_))) - ); - test!( - data_declaration, - "typedef type_identifier;", - Ok((_, DataDeclaration::TypeDeclaration(_))) - ); - test!( - data_declaration, - "typedef C::T c_t;", - Ok((_, DataDeclaration::TypeDeclaration(_))) - ); - test!( - data_declaration, - "enum {red, yellow, green} light1, light2;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "enum bit [1:0] {IDLE, XX='x, S1=2'b01, S2=2'b10} state, next;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "enum integer {IDLE, XX='x, S1='b01, S2='b10} state, next;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "enum integer {IDLE, XX='x, S1='b01, S2='b10} state, next;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "enum {bronze=3, silver, gold} medal;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "enum {a=3, b=7, c} alphabet;", - Ok((_, DataDeclaration::Variable(_))) - ); - test!( - data_declaration, - "enum bit [3:0] {bronze='h3, silver, gold='h5} medal2;", - Ok((_, DataDeclaration::Variable(_))) - ); test!( data_declaration, "integer i_array[*];", @@ -940,14 +647,10 @@ fn test_clause5() { Ok((_, _)) ); test!( - module_item, - r##"typedef struct {int a; shortreal b;} ab;"##, - Ok((_, _)) - ); - test!(module_item, r##"ab c;"##, Ok((_, _))); - test!( - module_item, - r##"c = '{0, 0.0}; // structure literal type determined from + many1(module_item), + r##"typedef struct {int a; shortreal b;} ab; + ab c; + c = '{0, 0.0}; // structure literal type determined from // the left-hand context (c)"##, Ok((_, _)) ); @@ -957,18 +660,10 @@ fn test_clause5() { Ok((_, _)) ); test!( - module_item, - r##"c = '{a:0, b:0.0}; // member name and value for that member"##, - Ok((_, _)) - ); - test!( - module_item, - r##"c = '{default:0}; // all elements of structure c are set to 0"##, - Ok((_, _)) - ); - test!( - module_item, - r##"d = ab'{int:1, shortreal:1.0}; // data type and default value for all + many1(module_item), + r##"c = '{a:0, b:0.0}; // member name and value for that member + c = '{default:0}; // all elements of structure c are set to 0 + d = ab'{int:1, shortreal:1.0}; // data type and default value for all // members of that type"##, Ok((_, _)) ); @@ -978,14 +673,12 @@ fn test_clause5() { Ok((_, _)) ); test!( - module_declaration, - r##"module test; - struct {int X,Y,Z;} XYZ = '{3{1}}; - typedef struct {int a,b[4];} ab_t; - int a,b,c; - ab_t v1[1:0] [2:0]; - v1 = '{2{'{3{'{a,'{2{b,c}}}}}}}; - endmodule"##, + many1(module_item), + r##"struct {int X,Y,Z;} XYZ = '{3{1}}; + typedef struct {int a,b[4];} ab_t; + int a,b,c; + ab_t v1[1:0] [2:0]; + v1 = '{2{'{3{'{a,'{2{b,c}}}}}}};"##, Ok((_, _)) ); test!( @@ -1023,13 +716,11 @@ fn test_clause5() { Ok((_, _)) ); test!( - module_item, - r##"(* fsm_state *) logic [7:0] state1;"##, - Ok((_, _)) - ); - test!( - module_item, - r##"(* fsm_state=1 *) logic [3:0] state2, state3;"##, + many1(module_item), + r##"(* fsm_state *) logic [7:0] state1; + (* fsm_state=1 *) logic [3:0] state2, state3; + logic [3:0] reg1; // reg1 does NOT have fsm_state set + (* fsm_state=0 *) logic [3:0] reg2; // nor does reg2"##, Ok((_, _)) ); test!( @@ -1051,4 +742,1087 @@ fn test_clause5() { } #[test] -fn test_debug() {} +fn test_clause6() { + test!( + many1(module_item), + r##"trireg a; // trireg net of charge strength medium + trireg (large) #(0,0,50) cap1; // trireg net of charge strength large + // with charge decay time 50 time units + trireg (small) signed [3:0] cap2; // signed 4-bit trireg vector of + // charge strength small"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"struct { + bit [7:0] A; + bit [7:0] B; + byte C; + } abc;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"assign abc.C = sel ? 8'hBE : 8'hEF; + + not (abc.A[0],abc.B[0]), + (abc.A[1],abc.B[1]), + (abc.A[2],abc.B[2]), + (abc.A[3],abc.B[3]); + + always @(posedge clk) abc.B <= abc.B + 1;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"assign abc.C = sel ? 8'hDE : 8'hED; + + // Mixing continuous and procedural assignments to abc.A[3] + always @(posedge clk) abc.A[7:3] <= !abc.B[7:3];"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"wire w = vara & varb; // net with a continuous assignment + + logic v = consta & constb; // variable with initialization + + logic vw; // no initial assignment + assign vw = vara & varb; // continuous assignment to a variable + + real circ; + assign circ = 2.0 * PI * R; // continuous assignment to a variable"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef struct { + real field1; + bit field2; + } T; + + // user-defined resolution function Tsum + function automatic T Tsum (input T driver[]); + Tsum.field1 = 0.0; + foreach (driver[i]) + Tsum.field1 += driver[i].field1; + endfunction + + nettype T wT; // an unresolved nettype wT whose data type is T + + // a nettype wTsum whose data type is T and + // resolution function is Tsum + nettype T wTsum with Tsum; + + // user-defined data type TR + typedef real TR[5]; + + // an unresolved nettype wTR whose data type + // is an array of real + nettype TR wTR; + + // declare another name nettypeid2 for nettype wTsum + nettype wTsum nettypeid2;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"class Base #(parameter p = 1); + typedef struct { + real r; + bit[p-1:0] data; + } T; + + static function T Tsum (input T driver[]); + Tsum.r = 0.0; + Tsum.data = 0; + foreach (driver[i]) + Tsum.data += driver[i].data; + Tsum.r = $itor(Tsum.data); + endfunction + endclass + + typedef Base#(32) MyBaseT; + nettype MyBaseT::T narrowTsum with MyBaseT::Tsum; + + typedef Base#(64) MyBaseType; + nettype MyBaseType::T wideTsum with MyBaseType::Tsum; + + narrowTsum net1; // data is 32 bits wide + wideTsum net2; // data is 64 bits wide"##, + Ok((_, _)) + ); + test!( + source_text, + r##"package NetsPkg; + nettype real realNet; + endpackage : NetsPkg + + module top(); + interconnect [0:1] iBus; + lDriver l1(iBus[0]); + rDriver r1(iBus[1]); + rlMod m1(iBus); + endmodule : top + + module lDriver(output wire logic out); + endmodule : lDriver + + module rDriver + import NetsPkg::*; + (output realNet out); + endmodule : rDriver + + module rlMod(input interconnect [0:1] iBus); + lMod l1(iBus[0]); + rMod r1(iBus[1]); + endmodule : rlMod"##, + Ok((_, _)) + ); + test!( + library_text, + r##"library realLib *.svr; + library logicLib *.sv; + + config cfgReal; + design logicLib.top; + default liblist realLib logicLib; + endconfig + + config cfgLogic; + design logicLib.top; + default liblist logicLib realLib; + endconfig"##, + Ok((_, _)) + ); + test!( + source_text, + r##"module top(); + interconnect [0:3] [0:1] aBus; + logic [0:3] dBus; + driver driverArray[0:3](aBus); + cmp cmpArray[0:3](aBus,rst,dBus); + endmodule : top"##, + Ok((_, _)) + ); + test!( + source_text, + r##"package NetsPkg; + nettype real realNet; + endpackage : NetsPkg"##, + Ok((_, _)) + ); + test!( + source_text, + r##"module driver + import NetsPkg::*; + #(parameter int delay = 30, + int iterations = 256) + (output realNet [0:1] out); + timeunit 1ns / 1ps; + real outR[1:0]; + assign out = outR; + initial begin + outR[0] = 0.0; + outR[1] = 3.3; + for (int i = 0; i < iterations; i++) begin + #delay outR[0] += 0.2; + outR[1] -= 0.2; + end + end + endmodule : driver"##, + Ok((_, _)) + ); + test!( + source_text, + r##"module driver #(parameter int delay = 30, + int iterations = 256) + (output wire logic [0:1] out); + timeunit 1ns / 1ps; + logic [0:1] outvar; + + assign out = outvar; + + initial begin + outvar = '0; + for (int i = 0; i < iterations; i++) + #delay outvar++; + end + endmodule : driver"##, + Ok((_, _)) + ); + test!( + source_text, + r##"module cmp + import NetsPkg::*; + #(parameter real hyst = 0.65) + (input realNet [0:1] inA, + input logic rst, + output logic out); + timeunit 1ns / 1ps; + real updatePeriod = 100.0; + + initial out = 1'b0; + + always #updatePeriod begin + if (rst) out <= 1'b0; + else if (inA[0] > inA[1]) out <= 1'b1; + else if (inA[0] < inA[1] - hyst) out <= 1'b0; + end + endmodule : cmp"##, + Ok((_, _)) + ); + test!( + source_text, + r##"module cmp #(parameter real hyst = 0.65) + (input wire logic [0:1] inA, + input logic rst, + output logic out); + + initial out = 1'b0; + + always @(inA, rst) begin + if (rst) out <= 1'b0; + else if (inA[0] & ~inA[1]) out <= 1'b1; + else out <= 1'b0; + end + endmodule : cmp"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"trireg (large) logic #(0,0,0) cap1; + typedef logic [31:0] addressT; + wire addressT w1; + wire struct packed { logic ecc; logic [7:0] data; } memsig;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"wire w; // equivalent to "wire logic w;" + wire [15:0] ww; // equivalent to "wire logic [15:0] ww;""##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"tri reg r; + inout wire reg p;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"interconnect w1; // legal + interconnect [3:0] w2; // legal + interconnect [3:0] w3 [1:0]; // legal"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"nettype T wT; + + // a nettype wTsum whose data type is T and + // resolution function is Tsum + // Refer to example in 6.6.7 for the declaration of Tsum + nettype T wTsum with Tsum; + + // a net of unresolved nettype wT + wT w1; + + // an array of nets, each net element is of unresolved nettype wT + wT w2[8]; + + // a net of resolved nettype wTsum and resolution function Tsum + wTsum w3; + + // an array of nets, each net is of resolved nettype wTsum + wTsum w4[8]; + + // user-defined data type TR which is an array of reals + typedef real TR[5]; + + // an unresolved nettype wTR with data type TR + nettype TR wTR; + + // a net with unresolved nettype wTR and data type TR + wTR w5; + + // an array of nets, each net has an unresolved nettype wTR + // and data type TR + wTR w6[8];"##, + Ok((_, _)) + ); + test!(many1(module_item), r##"shortint s1, s2[0:9];"##, Ok((_, _))); + test!( + many1(module_item), + r##"var byte my_byte; // equivalent to "byte my_byte;" + var v; // equivalent to "var logic v;" + var [15:0] vw; // equivalent to "var logic [15:0] vw;" + var enum bit { clear, error } status; + input var logic data_in; + var reg r;"##, + Ok((_, _)) + ); + test!(many1(module_item), r##"int i = 0;"##, Ok((_, _))); + test!( + many1(module_item), + r##"wand w; // a scalar "wand" net + tri [15:0] busa; // a 16-bit bus + trireg (small) storeit; // a charge storage node of strength small + logic a; // a scalar variable + logic[3:0] v; // a 4-bit vector made up of (from most to + // least significant)v[3], v[2], v[1], and v[0] + logic signed [3:0] signed_reg; // a 4-bit vector in range -8 to 7 + logic [-1:4] b; // a 6-bit vector + wire w1, w2; // declares two nets + logic [4:0] x, y, z; // declares three 5-bit variables"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"tri1 scalared [63:0] bus64; //a bus that will be expanded + tri vectored [31:0] data; //a bus that may or may not be expanded"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"int unsigned ui; + int signed si;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"chandle variable_name ;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"parameter string default_name = "John Smith"; + string myName = default_name;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"byte c = "A"; // assigns to c "A" + bit [10:0] b = "\x41"; // assigns to b 'b000_0100_0001 + bit [1:4][7:0] h = "hello" ; // assigns to h "ello""##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"string s0 = "String literal assign";// sets s0 to "String literal assign" + string s1 = "hello\0world"; // sets s1 to "helloworld" + bit [11:0] b = 12'ha41; + string s2 = string'(b); // sets s2 to 16'h0a41"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef logic [15:0] r_t; + r_t r; + integer i = 1; + string b = ""; + string a = {"Hi", b}; + + r = r_t'(a); // OK + b = string'(r); // OK + b = "Hi"; // OK + b = {5{"Hi"}}; // OK + a = {i{"Hi"}}; // OK (non-constant replication) + r = {i{"Hi"}}; // invalid (non-constant replication) + a = {i{b}}; // OK + a = {a,b}; // OK + a = {"Hi",b}; // OK + r = {"H",""}; // yields "H\0". "" is converted to 8'b0 + b = {"H",""}; // yields "H". "" is the empty string + a[0] = "h"; // OK, same as a[0] = "cough" + a[0] = b; // invalid, requires a cast + a[1] = "\0"; // ignored, a is unchanged"##, + Ok((_, _)) + ); + //test!( + // many1(module_item), + // r##"str = "123"; + // int i = str.atoi(); // assigns 123 to i."##, + // Ok((_, _)) + //); + test!( + many1(module_item), + r##"event done; // declare a new event called done + event done_too = done; // declare done_too as alias to done + event empty = null; // event variable with no synchronization object"##, + Ok((_, _)) + ); + test!(many1(module_item), r##"typedef int intP;"##, Ok((_, _))); + test!(many1(module_item), r##"intP a, b;"##, Ok((_, _))); + test!( + source_text, + r##"interface intf_i; + typedef int data_t; + endinterface + + module sub(intf_i p); + typedef p.data_t my_data_t; + my_data_t data; + // type of 'data' will be int when connected to interface above + endmodule"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef enum type_identifier; + typedef struct type_identifier; + typedef union type_identifier; + typedef class type_identifier; + typedef interface class type_identifier; + typedef type_identifier;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef C; + C::T x; // illegal; C is an incomplete forward type + typedef C::T c_t; // legal; reference to C::T is made by a typedef + c_t y; + class C; + typedef int T; + endclass"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"enum {red, yellow, green} light1, light2; // anonymous int type"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"enum bit [1:0] {IDLE, XX='x, S1=2'b01, S2=2'b10} state, next;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"enum integer {IDLE, XX='x, S1='b01, S2='b10} state, next;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"enum integer {IDLE, XX='x, S1, S2} state, next;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"enum {bronze=3, silver, gold} medal; // silver=4, gold=5"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"enum {a=3, b=7, c} alphabet;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"enum {a=0, b=7, c, d=8} alphabet;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"enum {a, b=7, c} alphabet;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"enum bit [3:0] {bronze='h3, silver, gold='h5} medal2; + + // Correct declaration - bronze and gold sizes are redundant + enum bit [3:0] {bronze=4'h3, silver, gold=4'h5} medal3; + + // Error in the bronze and gold member declarations + enum bit [3:0] {bronze=5'h13, silver, gold=3'h5} medal4; + + // Error in c declaration, requires at least 2 bits + enum bit [0:0] {a,b,c} alphabet;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef enum {NO, YES} boolean; + boolean myvar; // named type"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef enum { add=10, sub[5], jmp[6:8] } E1;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"enum { register[2] = 1, register[2:4] = 10 } vr;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef enum { red, green, blue, yellow, white, black } Colors;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef enum { red, green, blue, yellow, white, black } Colors; + + Colors col; + integer a, b; + + a = blue * 3; + col = yellow; + b = col + green;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef enum {Red, Green, Blue} Colors; + typedef enum {Mo,Tu,We,Th,Fr,Sa,Su} Week; + Colors C; + Week W; + int I; + + C = Colors'(C+1); // C is converted to an integer, then added to + // one, then converted back to a Colors type + + C = Colors'(Su); // Legal; puts an out of range value into C + + I = C + W; // Legal; C and W are automatically cast to int"##, + Ok((_, _)) + ); + //test!( + // many1(module_item), + // r##"typedef enum { red, green, blue, yellow } Colors; + // Colors c = c.first; + // forever begin + // $display( "%s : %d\n", c.name, c ); + // if( c == c.last ) break; + // c = c.next; + // end"##, + // Ok((_, _)) + //); + test!( + many1(module_item), + r##"localparam byte colon1 = ":" ; + specparam delay = 10 ; // specparams are used for specify blocks + parameter logic flag = 1 ;"##, + Ok((_, _)) + ); + test!( + source_text, + r##"class vector #(size = 1); // size is a parameter in a parameter port list + logic [size-1:0] v; + endclass + interface simple_bus #(AWIDTH = 64, type T = word) // parameter port list + (input logic clk) ; // port list + endinterface"##, + Ok((_, _)) + ); + //test!( + // source_text, + // r##"module mc #(int N = 5, M = N*16, type T = int, T x = 0) + // (); + // endmodule"##, + // Ok((_, _)) + //); + test!( + source_text, + r##"class Mem #(type T, int size); + T words[size]; + endclass + + typedef Mem#(byte, 1024) Kbyte;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"parameter msb = 7; // defines msb as a constant value 7 + parameter e = 25, f = 9; // defines two constant numbers + parameter r = 5.7; // declares r as a real parameter + parameter byte_size = 8, + byte_mask = byte_size - 1; + parameter average_delay = (r + f) / 2; + + parameter signed [3:0] mux_selector = 0; + parameter real r1 = 3.5e17; + parameter p1 = 13'h7e; + parameter [31:0] dec_const = 1'b1; // value converted to 32 bits + parameter newconst = 3'h4; // implied range of [2:0] + parameter newconst = 4; // implied range of at least [31:0]"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"parameter logic [31:0] P1 [3:0] = '{ 1, 2, 3, 4 } ; // unpacked array + // parameter declaration"##, + Ok((_, _)) + ); + //test!( + // many1(module_item), + // r##"parameter r2 = $; + // property inq1(r1,r2); + // @(posedge clk) a ##[r1:r2] b ##1 c |=> d; + // endproperty + // assert property (inq1(3, r2));"##, + // Ok((_, _)) + //); + //test!( + // many1(module_item), + // r##"interface quiet_time_checker #(parameter min_quiet = 0, + // parameter max_quiet = 0) + // (input logic clk, reset_n, logic [1:0]en); + + // generate + // if ( max_quiet == 0) begin + // property quiet_time; + // @(posedge clk) reset_n |-> ($countones(en) == 1); + // endproperty + // a1: assert property (quiet_time); + // end + // else begin + // property quiet_time; + // @(posedge clk) + // (reset_n && ($past(en) != 0) && en == 0) + // |->(en == 0)[*min_quiet:max_quiet] + // ##1 ($countones(en) == 1); + // endproperty + // a1: assert property (quiet_time); + // end + // if ((min_quiet == 0) && ($isunbounded(max_quiet)) + // $warning(warning_msg); + // endgenerate + // endinterface + + // quiet_time_checker #(0, 0) quiet_never (clk,1,enables); + // quiet_time_checker #(2, 4) quiet_in_window (clk,1,enables); + // quiet_time_checker #(0, $) quiet_any (clk,1,enables);"##, + // Ok((_, _)) + //); + //test!( + // many1(module_item), + // r##"interface width_checker #(parameter min_cks = 1, parameter max_cks = 1) + // (input logic clk, reset_n, expr); + // generate + // if ($isunbounded(max_cks)) begin + // property width; + // @(posedge clk) + // (reset_n && $rose(expr)) |-> (expr [* min_cks]); + // endproperty + // a2: assert property (width); + // end + // else begin + // property assert_width_p; + // @(posedge clk) + // (reset_n && $rose(expr)) |-> (expr[* min_cks:max_cks]) + // ##1 (!expr); + // endproperty + // a2: assert property (width); + // end + // endgenerate + // endinterface + + // width_checker #(3, $) max_width_unspecified (clk,1,enables); + // width_checker #(2, 4) width_specified (clk,1,enables);"##, + // Ok((_, _)) + //); + test!( + source_text, + r##"module ma #( parameter p1 = 1, parameter type p2 = shortint ) + (input logic [p1:0] i, output logic [p1:0] o); + p2 j = 0; // type of j is set by a parameter, (shortint unless redefined) + always @(i) begin + o = i; + j++; + end + endmodule + module mb; + logic [3:0] i,o; + ma #(.p1(3), .p2(int)) u1(i,o); //redefines p2 to a type of int + endmodule"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"specify + specparam tRise_clk_q = 150, tFall_clk_q = 200; + specparam tRise_control = 40, tFall_control = 50; + endspecify"##, + Ok((_, _)) + ); + test!( + source_text, + r##"module RAM16GEN ( output [7:0] DOUT, + input [7:0] DIN, + input [5:0] ADR, + input WE, CE); + specparam dhold = 1.0; + specparam ddly = 1.0; + parameter width = 1; + parameter regsize = dhold + 1.0; // Illegal - cannot assign + // specparams to parameters + endmodule"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"const logic option = a.b.c ;"##, + Ok((_, _)) + ); + //test!( + // many1(module_item), + // r##"const class_name object = new(5,3);"##, + // Ok((_, _)) + //); + test!( + source_text, + r##"module msl; + int st0; // static + initial begin + int st1; // static + static int st2; // static + automatic int auto1; // automatic + end + task automatic t1(); + int auto2; // automatic + static int st3; // static + automatic int auto3; // automatic + endtask + endmodule"##, + Ok((_, _)) + ); + test!( + source_text, + r##"module top_legal; + int svar1 = 1; // static keyword optional + initial begin + for (int i=0; i<3; i++) begin + automatic int loop3 = 0; // executes every loop + for (int j=0; j<3; j++) begin + loop3++; + $display(loop3); + end + end // prints 1 2 3 1 2 3 1 2 3 + for (int i=0; i<3; i++) begin + static int loop2 = 0; // executes once at time zero + for (int j=0; j<3; j++) begin + loop2++; + $display(loop2); + end + end // prints 1 2 3 4 5 6 7 8 9 + end + endmodule : top_legal + + module top_illegal; // should not compile + initial begin + int svar2 = 2; // static/automatic needed to show intent + for (int i=0; i<3; i++) begin + int loop3 = 0; // illegal statement + for (int i=0; i<3; i++) begin + loop3++; + $display(loop3); + end + end + end + endmodule : top_illegal"##, + Ok((_, _)) + ); + test!( + source_text, + r##"program automatic test ; + int i; // not within a procedural block - static + task t ( int a ); // arguments and variables in t are automatic + endtask + endprogram"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef bit node; // 'bit' and 'node' are matching types + typedef type1 type2; // 'type1' and 'type2' are matching types"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"struct packed {int A; int B;} AB1, AB2; // AB1, AB2 have matching types + struct packed {int A; int B;} AB3; // the type of AB3 does not match + // the type of AB1"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef struct packed {int A; int B;} AB_t; + AB_t AB1; AB_t AB2; // AB1 and AB2 have matching types + + typedef struct packed {int A; int B;} otherAB_t; + otherAB_t AB3; // the type of AB3 does not match the type of AB1 or AB2"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef bit signed [7:0] BYTE; // matches the byte type + typedef bit signed [0:7] ETYB; // does not match the byte type"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef byte MEM_BYTES [256]; + typedef bit signed [7:0] MY_MEM_BYTES [256]; // MY_MEM_BYTES matches + // MEM_BYTES + + typedef logic [1:0] [3:0] NIBBLES; + typedef logic [7:0] MY_BYTE; // MY_BYTE and NIBBLES are not matching types + + typedef logic MD_ARY [][2:0]; + typedef logic MD_ARY_TOO [][0:2]; // Does not match MD_ARY"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef byte signed MY_CHAR; // MY_CHAR matches the byte type"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"struct {int A; int B;} AB1, AB2; // AB1, AB2 have equivalent types + struct {int A; int B;} AB3; // AB3 is not type equivalent to AB1"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef bit signed [7:0] BYTE; // equivalent to the byte type + typedef struct packed signed {bit[3:0] a, b;} uint8; + // equivalent to the byte type"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"bit [9:0] A [0:5]; + bit [1:10] B [6]; + typedef bit [10:1] uint10; + uint10 C [6:1]; // A, B and C have equivalent types + typedef int anint [0:0]; // anint is not type equivalent to int"##, + Ok((_, _)) + ); + test!( + source_text, + r##"package p1; + typedef struct {int A;} t_1; + endpackage + + typedef struct {int A;} t_2; + + module sub(); + import p1::t_1; + parameter type t_3 = int; + parameter type t_4 = int; + typedef struct {int A;} t_5; + t_1 v1; t_2 v2; t_3 v3; t_4 v4; t_5 v5; + endmodule + + module top(); + typedef struct {int A;} t_6; + sub #(.t_3(t_6)) s1 (); + sub #(.t_3(t_6)) s2 (); + + initial begin + s1.v1 = s2.v1; // legal - both types from package p1 (rule 8) + s1.v2 = s2.v2; // legal - both types from $unit (rule 4) + s1.v3 = s2.v3; // legal - both types from top (rule 2) + s1.v4 = s2.v4; // legal - both types are int (rule 1) + s1.v5 = s2.v5; // illegal - types from s1 and s2 (rule 4) + end + endmodule"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"nettype nettypeid1 nettypeid2;"##, + Ok((_, _)) + ); + //test!( + // many1(module_item), + // r##"var type(a+b) c, d; + // c = type(i+3)'(v[15:0]);"##, + // Ok((_, _)) + //); + test!( + many1(module_item), + r##"localparam type T = type(bit[12:0]);"##, + Ok((_, _)) + ); + //test!( + // many1(module_item), + // r##"bit [12:0] A_bus, B_bus; + // parameter type bus_t = type(A_bus); + // generate + // case (type(bus_t)) + // type(bit[12:0]): addfixed_int #(bus_t) (A_bus,B_bus); + // type(real): add_float #(type(A_bus)) (A_bus,B_bus); + // endcase + // endgenerate"##, + // Ok((_, _)) + //); + test!( + many1(module_item), + r##"A = cast_t1'(expr_1) + cast_t2'(expr_2);"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"cast_t1 temp1; + cast_t2 temp2; + + temp1 = expr_1; + temp2 = expr_2; + A = temp1 + temp2;"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"logic [7:0] regA; + logic signed [7:0] regS; + + regA = unsigned'(-4); // regA = 8'b11111100 + regS = signed'(4'b1100); // regS = -4"##, + Ok((_, _)) + ); + test!( + many1(module_item), + r##"typedef struct { + bit isfloat; + union { int i; shortreal f; } n; // anonymous type + } tagged_st; // named structure + + typedef bit [$bits(tagged_st) - 1 : 0] tagbits; // tagged_st defined above + + tagged_st a [7:0]; // unpacked array of structures + + tagbits t = tagbits'(a[3]); // convert structure to array of bits + a[4] = tagged_st'(t); // convert array of bits back to structure"##, + Ok((_, _)) + ); + //test!( + // many1(module_item), + // r##"typedef enum { red, green, blue, yellow, white, black } Colors; + // Colors col; + // $cast( col, 2 + 3 );"##, + // Ok((_, _)) + //); + //test!( + // many1(module_item), + // r##"if ( ! $cast( col, 2 + 8 ) ) // 10: invalid cast + // $display( "Error in cast" );"##, + // Ok((_, _)) + //); + test!(many1(module_item), r##"col = Colors'(2 + 3);"##, Ok((_, _))); + test!(many1(module_item), r##"B = dest_t'(A);"##, Ok((_, _))); + test!( + many1(module_item), + r##"struct {bit[7:0] a; shortint b;} a; + int b = int'(a); + + // Illegal conversion from 20-bit struct to int (32 bits) - run time error + struct {bit a[$]; shortint b;} a = {{1,2,3,4}, 67}; + int b = int'(a); + + // Illegal conversion from int (32 bits) to struct dest_t (25 or 33 bits), + // compile time error + typedef struct {byte a[$]; bit b;} dest_t; + int a; + dest_t b = dest_t'(a);"##, + Ok((_, _)) + ); + //test!( + // many1(module_item), + // r##"typedef struct { + // shortint address; + // logic [3:0] code; + // byte command [2]; + // } Control; + + // typedef bit Bits [36:1]; + + // Control p; + // Bits stream[$]; + + // stream.push_back(Bits'(p)); // append packet to unpacked queue of Bits + // Bits b; + // Control q; + // b = stream.pop_front(); // get packet (as Bits) from stream + // q = Control'(b); // convert packet bits back to a Control packet"##, + // Ok((_, _)) + //); + test!( + many1(module_item), + r##"typedef struct { + byte length; + shortint address; + byte payload[]; + byte chksum; + } Packet;"##, + Ok((_, _)) + ); + //test!( + // many1(module_item), + // r##"function Packet genPkt(); + // Packet p; + + // void'( randomize( p.address, p.length, p.payload ) + // with { p.length > 1 && p.payload.size == p.length; } ); + // p.chksum = p.payload.xor(); + // return p; + // endfunction"##, + // Ok((_, _)) + //); + test!( + many1(module_item), + r##"typedef byte channel_type[$]; + channel_type channel; + channel = {channel, channel_type'(genPkt())};"##, + Ok((_, _)) + ); + //test!( + // many1(module_item), + // r##"Packet p; + // int size; + + // size = channel[0] + 4; + // p = Packet'( channel[0 : size - 1] ); // convert stream to Packet + // channel = channel[ size : $ ]; // update the stream so it now + // // lacks that packet"##, + // Ok((_, _)) + //); + test!( + source_text, + r##"virtual class C#(parameter type T = logic, parameter SIZE = 1); + typedef logic [SIZE-1:0] t_vector; + typedef T t_array [SIZE-1:0]; + typedef struct { + t_vector m0 [2*SIZE-1:0]; + t_array m1; + } t_struct; + endclass"##, + Ok((_, _)) + ); + test!( + source_text, + r##"module top (); + typedef logic [7:0] t_t0; + C#(t_t0,3)::t_vector v0; + C#(t_t0,3)::t_array a0; + C#(bit,4)::t_struct s0; + endmodule"##, + Ok((_, _)) + ); +} + +#[test] +fn test_debug() { + test!( + many1(module_item), + r##"str = "123"; + int i = str.atoi(); // assigns 123 to i."##, + Ok((_, _)) + ); +} diff --git a/sv-parser-parser/src/utils.rs b/sv-parser-parser/src/utils.rs index 69da96b..d124225 100644 --- a/sv-parser-parser/src/utils.rs +++ b/sv-parser-parser/src/utils.rs @@ -472,9 +472,12 @@ where let mut ret = Vec::new(); loop { if let Ok((t, b)) = f(s) { - let (u, c) = g(t)?; - s = u; - ret.push((b, c)); + if let Ok((u, c)) = g(t) { + s = u; + ret.push((b, c)); + } else { + break; + } } else { break; } diff --git a/sv-parser-syntaxtree/src/source_text/library_source_text.rs b/sv-parser-syntaxtree/src/source_text/library_source_text.rs index 4c328a0..8af878b 100644 --- a/sv-parser-syntaxtree/src/source_text/library_source_text.rs +++ b/sv-parser-syntaxtree/src/source_text/library_source_text.rs @@ -32,6 +32,12 @@ pub struct IncludeStatement { } #[derive(Clone, Debug, Node)] -pub struct FilePathSpec { - pub nodes: (StringLiteral,), +pub enum FilePathSpec { + Literal(StringLiteral), + NonLiteral(FilePathSpecNonLiteral), +} + +#[derive(Clone, Debug, Node)] +pub struct FilePathSpecNonLiteral { + pub nodes: (Locate, Vec), }