Re: [myhdl-list] & quot; Error in user defined VHDL code& quot; should show line, and colum
Brought to you by:
jandecaluwe
From: Angel E. <ang...@gm...> - 2010-07-04 22:00:18
|
Jan Decaluwe <jan <at> jandecaluwe.com> writes: > > Angel Ezquerra wrote: > > Jan Decaluwe <jan <at> jandecaluwe.com> writes: > > > >> Error messages are often a weak point, but I thought that in the > >> particular case of user-defined code, it was reasonable. I don't > >> immediately understand what you describe here, a small example > >> welcome. > > > > I got the following error message while trying to use a very long > > VHDL user defined string on one of my myhdl python files: > > > > "raise ToVHDLError("Error in user defined VHDL code", msg, info) > > myhdl.ToVHDLError: in file dsp48e.py, function dsp48e starting on > > line 3: > > Error in user defined VHDL code: <type 'exceptions.ValueError'>: > > unsupported format character ',' (0x2c) at index 6175" > > > > As you can see, the error indicates "index 6175" as the place where the > > error happened. I assume that that refers to the 6175 character on the > > __vhdl__ string. If that is the case, while it would actually be > > possible to use that information to find where the error happened, > > it is definitelly not very practical to do so! Instead it would be > > much better if the error message told you that the error happened > > on line 89, column 12 of the __vhdl__ string, or, even better, > > on line 101, column 20 of the original python script. > > So you get the exact file, function, error condition, index in the string > and even the offending character, and this is not good enough Mm. As I said you _can_ find the error. That does not mean that it is easy :-) Jokes aside, not many editors support going straight to a string offset, which makes this error message much less useful that it could be in practice. > When something is wrong with the format string evaluation, MyHDL forwards > you whatever exception Python gives it. So this is pretty much what > native python would tell you. There are a myriad things that can go > wrong, and the error may be Python-version dependent. What you are > asking is combining the MyHDL info with the specific Python info, > which is probably unfeasible in practical terms. I agree that you cannot foresee all types of errors on the user generated code. However this is an error which happens at the boundary between the Python and the user-defined VHDL code. It is at that point were any error generated by the python interpreter will be less specific. Thus, anything that could be done to improve that would be nice. For example, it would be quite straight forward to detect this sort of error and show the offending line in the user defined code string. This would make it very easy to find the problem and fix it. To that end, I digged a bit through the myhdl code and I saw that this error is generated on the line 334 of the _toVHDL.py file (on the _convertGens() function, to be exact). The line says: blockBuf.write(str(tree)) This function calls the seems to call the __str__() method of the _UserCode class. This makes me believe that this is basically the most common if not the only error that MyHDL can detect on the user defined code. So, as an exercise I applied the following patch: diff --git a/myhdl/_extractHierarchy.py b/myhdl/_extractHierarchy.py --- a/myhdl/_extractHierarchy.py +++ b/myhdl/_extractHierarchy.py @@ -101,10 +101,35 @@ class _UserCode(object): info = "in file %s, function %s starting on line %s:\n " % \ (self.sourcefile, self.funcname, self.sourceline) msg = "%s: %s" % (type, value) + + # Check whether the error contains a reference + # to a position in the code string + s_index_tag = " at index " + i_error_index_position = msg.find(s_index_tag) + if i_error_index_position != -1: + # The error string contains an index -> extract + # the corresponding line + i_error_index_position += len(s_index_tag) + i_error_position = int(msg[i_error_index_position:]) + i_error_line_start = 1 + self.code[:i_error_position].rfind("\n") + i_error_line_end = i_error_position + \ + self.code[i_error_position:].find("\n") + s_error_line = self.code[i_error_line_start:i_error_line_end] + + # And get the error column and line + n_error_column = i_error_position - i_error_line_start + n_error_line = len(self.code[:i_error_position].splitlines()) + print("ERROR in line %d, column %d: %s" % (n_error_line, \ + n_error_column, s_error_line)) + self.raiseError(msg, info) code = "\n%s\n" % code return code This is certainly not the most beautiful python code ever, but it shows the information that I think would best help you find these sorts of errors :-) Cheers, Angel |