Shop OBEX P1 Docs P2 Docs Learn Events
Aiming for a clean P1V compile? (and anyone added a simple UART?) — Parallax Forums

Aiming for a clean P1V compile? (and anyone added a simple UART?)

Cluso99Cluso99 Posts: 18,069
edited 2015-06-04 05:21 in Propeller 1
Postedit: Change heading

Has anyone added a simple UART to their P1V?

And has anyone done a clean compile of the P1V?

Comments

  • ozpropdevozpropdev Posts: 2,792
    edited 2015-04-02 20:18
    Cluso99 wrote: »
    And has anyone done a clean compile of the P1V?

    Not sure what you mean bu a "clean" compile?
    Do you mean no warnings in the compilation report?

    P.S. Not yet on the UART question.
  • LeonLeon Posts: 7,620
    edited 2015-04-03 02:58
    What's wrong with implementing a UART in the usual way, with software?
  • Heater.Heater. Posts: 21,230
    edited 2015-04-03 03:23
    @Leon,

    A UART in COG is regarded by many as a terrible waste of a 32 bit processor and 2K of RAM.

    If you can build a P1 for FPGA why not add a little logic for a UART, it's no worse an idea than the Prop having counters or video generators.

    In fact arguably the Prop would be better off with having hardware UARTs than video generators.

    @Cluso

    How are you thinking this should be done?

    Should there be one UART per COG in the manner of video hardware? With some special registers in COG space. Perhaps replacing the video registers.

    Should there be a UART as a shared HUB resource.

    Or instead of using registers would there be UART instructions like the lock instructions?
  • ozpropdevozpropdev Posts: 2,792
    edited 2015-04-03 03:58
    The "old" P2 had 2 * UART's per cog with supporting instructions.
    They were very easy to use and fast!
  • Cluso99Cluso99 Posts: 18,069
    edited 2015-04-03 06:52
    i mean a clean compile without errors.

    For the UART, I just want a simple single UART. Not a standard UART with error flags looking like a 16450 style, but like the pair Chip did in the P2.

    I intend to remove the Video so I can use those registers for Tx and Rx.

    I am going to compile a single cog with the hub available at full cog speed, and available as extended cog ram too. By changing JMPRET and TJ/DJ to relative and making the pc 14 bits (long address) I can execute from extended cog / hub ram.

    Hence my need for a simple UART to communicate with th PC.
  • SeairthSeairth Posts: 2,474
    edited 2015-04-03 07:01
    Cluso99 wrote: »
    i mean a clean compile without errors.

    I haven't had any problems (currently on Quartus II 14.1 for Windows). Because I didn't like timing warnings, I wrote an SDC file for the DE0-Nano (I don't have a DE2-115 and the Cyclone V on the BEMicro CV is tricky) that lets TimeQuest do its thing without warnings. That file is currently pushed to jacgoudsmit's P1V fork (https://github.com/jacgoudsmit/P1V).

    What kind of compile errors are you seeing?
  • Cluso99Cluso99 Posts: 18,069
    edited 2015-04-03 07:52
    Seairth wrote: »
    I haven't had any problems (currently on Quartus II 14.1 for Windows). Because I didn't like timing warnings, I wrote an SDC file for the DE0-Nano (I don't have a DE2-115 and the Cyclone V on the BEMicro CV is tricky) that lets TimeQuest do its thing without warnings. That file is currently pushed to jacgoudsmit's P1V fork (https://github.com/jacgoudsmit/P1V).

    What kind of compile errors are you seeing?
    It was the timing errors. I haven't done any compiling for many months.

    Since I am going to be playing around with potential timing problems I want to start with a clean compile.

    So thanks... I will download and compile.
  • pik33pik33 Posts: 2,366
    edited 2015-04-03 09:27
    At least someone wrote them so there is a starting point :)

    These .sdc files are huge. Some hundred lines of code.... :(
  • SeairthSeairth Posts: 2,474
    edited 2015-04-03 10:04
    pik33 wrote: »
    At least someone wrote them so there is a starting point :)

    These .sdc files are huge. Some hundred lines of code.... :(

    True. And it's not very flexible, at least for those who want to add or remove cogs and or counters. Of course, it's all just tcl, so it's possible to write it a bit more generically. But I won't be getting around to that any time soon...
  • jac_goudsmitjac_goudsmit Posts: 418
    edited 2015-04-04 21:26
    Just a thought... In a way, the video hardware IS already sort of a parallel write-only UART: you give it the data to send, and it generates the data on up to 8 pins, timed by a programmable timer, while the cog is doing something else.

    I wonder how hard it would be to extend the functionality of the various registers to use it as a proper UART. After all, there are quite a number of unused bits in the video configuration registers...

    ===Jac
  • Cluso99Cluso99 Posts: 18,069
    edited 2015-04-04 22:56
    Just a thought... In a way, the video hardware IS already sort of a parallel write-only UART: you give it the data to send, and it generates the data on up to 8 pins, timed by a programmable timer, while the cog is doing something else.

    I wonder how hard it would be to extend the functionality of the various registers to use it as a proper UART. After all, there are quite a number of unused bits in the video configuration registers...

    ===Jac
    This all makes sense, but would depend on how much the extra logic adds vs adding a simple uart (like Chip did on the P2).
    We have used the VGA to send out clocked serial databits in the P1. It would have been nice to be able to input them serially too. It probably wasn't on Chip's mind when he designed the VGA.

    IIRC the video used quite a bit of the fpga, hence I cut down the VGA to only 1 or 2 cogs. I would think in reality we could set cogs say cogs 0 & 4 to have VGA, and cogs 1,2,3,5,6,7 to have UARTs. Then these cogs have access to the VGA registers and WaitVID instruction for UART registers and instructions.

    Jac,
    I downloaded the clean master from git. Nice job. It still reports 36 warnings although I think most are not relevant.

    I presume the top.tdf is the place to change to increase the clock...
        pll             : altpll with (
                            pll_type = "enhanced",
                            operation_mode = "normal",
                            inclk0_input_frequency = 20000,     -- 20000ps = 50MHz
                            clk0_multiply_by = 16,
                            clk0_divide_by = 5);
    
    I would like to try 96MHz (USB) and above. Anyway,I will just give it a try.
  • TubularTubular Posts: 4,702
    edited 2015-04-05 05:17
    Just a thought... In a way, the video hardware IS already sort of a parallel write-only UART: you give it the data to send, and it generates the data on up to 8 pins, timed by a programmable timer, while the cog is doing something else.

    I wonder how hard it would be to extend the functionality of the various registers to use it as a proper UART. After all, there are quite a number of unused bits in the video configuration registers...

    ===Jac

    I've been thinking something similar Jac. You could use FRQA/B to set the baud rate, and PHSA/B to read or write UART data. The CTRA/B config register, upon read, could identify how many bytes are in the RX buffer. The buffers themselves can be hidden behind the PHSA/B registers and be of the required depth.

    Hopefully its just a matter of substituting cog_ctra and cog_vid_. We could make other peripherals in a similar way too, it would make them easy to substitute.
  • jac_goudsmitjac_goudsmit Posts: 418
    edited 2015-04-05 22:40
    Cluso99 wrote: »
    IIRC the video used quite a bit of the fpga, hence I cut down the VGA to only 1 or 2 cogs. I would think in reality we could set cogs say cogs 0 & 4 to have VGA, and cogs 1,2,3,5,6,7 to have UARTs. Then these cogs have access to the VGA registers and WaitVID instruction for UART registers and instructions.

    I've been thinking of changing the video Verilog to reduce the video hardware too, but I would probably implement some sort of automatic allocation mechanism, linked to write-operations to any video register. Whichever cog is the first to write to any of the video registers, gets the video; when the cog stops, the video hardware is "freed" again. That way most existing SPIN/PASM software will still be compatible (as long as you don't run too many video cogs obviously). The allocation would need 8-to-1 multiplexers for each video register of course, and I don't know what the consequences would be for LE usage.

    Another option is to redesign the video hardware so that each pin group (0-7, 8-15, 16-23 and 24-31) has its own video hardware, instead of assigning video hardware to the cogs. This should save at least half of the video hardware but might be tricky to implement, in case of conflicts between cogs that are trying to control the same pin group.
    Jac,
    I downloaded the clean master from git. Nice job. It still reports 36 warnings although I think most are not relevant.

    I presume the top.tdf is the place to change to increase the clock...

    Thanks! I didn't make any changes to the code in my P1V github repo, I just reorganized it so that it would take less work to implement changes and port them between targets. The warnings are probably the same (timing) warnings of the original code. I've only done minimal testing because I didn't have a lab to hook up my BeMicro CV to anything worth really running an application.

    I've been working on other projects and I moved from Arizona to California last month, so I haven't had much time for P1V...

    ===Jac
  • Cluso99Cluso99 Posts: 18,069
    edited 2015-05-03 02:36
    In the search for a clean compile, I have found solutions to reduce the warnings from 16 to 11.

    By adding the files "top.tdf", "tim.tdf", "dig.v" to the project in Quartus removes 3 warnings.
    Project/Add Files/Files/Add (top.tdf, tim.tdf, dig.v)

    There must be a way to have these files included in the project without the need to modify the project in Quartus.
    Does anyone know how to solve this ???


    Here are the changes to hub_mem.v to remove 2 warnings (add the `ifndef... and `endif lines)
    // 4096 x 32 rom containing character definitions ($8000..$BFFF)
    
    `ifndef DISABLE_FONT_ROM
    (* ram_init_file = "hub_rom_low.hex" *)     reg [31:0] rom_low [4095:0];
    
    reg [31:0] rom_low_q;
    
    always @(posedge clk_cog)
    if (ena_bus && a[13:12] == 2'b10)
        rom_low_q <= rom_low[a[11:0]];
    `endif
    


    Here are the remaining 11 warnings (note the hub_mem.v line number is incorrect)
    Warning (276027): Inferred dual-clock RAM node "dig:core|cog:coggen[0].cog_|cog_ram:cog_ram_|altsyncram:r[0][31]__1" from synchronous design logic.  The read-during-write behavior of a dual-clock RAM is undefined and may not match the behavior of the original design.
    Warning (10858): Verilog HDL warning at hub_mem.v(102): object rom_high used but never assigned
    Warning (19016): Clock multiplexers are found and protected
    	Warning (19017): Found clock multiplexer dig:core|cog:coggen[7].cog_|cog_ctr:cog_ctra|Mux6
    	Warning (19017): Found clock multiplexer dig:core|cog:coggen[6].cog_|cog_ctr:cog_ctra|Mux6
    	Warning (19017): Found clock multiplexer dig:core|cog:coggen[5].cog_|cog_ctr:cog_ctra|Mux6
    	Warning (19017): Found clock multiplexer dig:core|cog:coggen[4].cog_|cog_ctr:cog_ctra|Mux6
    	Warning (19017): Found clock multiplexer dig:core|cog:coggen[3].cog_|cog_ctr:cog_ctra|Mux6
    	Warning (19017): Found clock multiplexer dig:core|cog:coggen[2].cog_|cog_ctr:cog_ctra|Mux6
    	Warning (19017): Found clock multiplexer dig:core|cog:coggen[1].cog_|cog_ctr:cog_ctra|Mux6
    	Warning (19017): Found clock multiplexer dig:core|cog:coggen[0].cog_|cog_ctr:cog_ctra|Mux6
    Warning (19016): Clock multiplexers are found and protected
    	Warning (19017): Found clock multiplexer tim:clkgen|clk_pll~2
    Warning (276020): Inferred RAM node "dig:core|hub:hub_|hub_mem:hub_mem_|ram3_rtl_0" from synchronous design logic.  Pass-through logic has been added to match the read-during-write behavior of the original design.
    Warning (276020): Inferred RAM node "dig:core|hub:hub_|hub_mem:hub_mem_|ram2_rtl_0" from synchronous design logic.  Pass-through logic has been added to match the read-during-write behavior of the original design.
    Warning (276020): Inferred RAM node "dig:core|hub:hub_|hub_mem:hub_mem_|ram1_rtl_0" from synchronous design logic.  Pass-through logic has been added to match the read-during-write behavior of the original design.
    Warning (276020): Inferred RAM node "dig:core|hub:hub_|hub_mem:hub_mem_|ram0_rtl_0" from synchronous design logic.  Pass-through logic has been added to match the read-during-write behavior of the original design.
    Warning (292013): Feature LogicLock is only available with a valid subscription license. You can purchase a software subscription to gain full access to this feature.
    Warning (15714): Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details
    Warning (169177): 34 pins must meet Altera requirements for 3.3-, 3.0-, and 2.5-V interfaces. For more information, refer to AN 447: Interfacing Cyclone IV E Devices with 3.3/3.0/2.5-V LVTTL/LVCMOS I/O Systems.
    	Info (169178): Pin io[0] uses I/O standard 3.3-V LVCMOS at J14
    	Info (169178): Pin io[1] uses I/O standard 3.3-V LVCMOS at J13
    	Info (169178): Pin io[2] uses I/O standard 3.3-V LVCMOS at K15
    	Info (169178): Pin io[3] uses I/O standard 3.3-V LVCMOS at J16
    	Info (169178): Pin io[4] uses I/O standard 3.3-V LVCMOS at L13
    	Info (169178): Pin io[5] uses I/O standard 3.3-V LVCMOS at M10
    	Info (169178): Pin io[6] uses I/O standard 3.3-V LVCMOS at N14
    	Info (169178): Pin io[7] uses I/O standard 3.3-V LVCMOS at L14
    	Info (169178): Pin io[8] uses I/O standard 3.3-V LVCMOS at P14
    	Info (169178): Pin io[9] uses I/O standard 3.3-V LVCMOS at N15
    	Info (169178): Pin io[10] uses I/O standard 3.3-V LVCMOS at N16
    	Info (169178): Pin io[11] uses I/O standard 3.3-V LVCMOS at R14
    	Info (169178): Pin io[12] uses I/O standard 3.3-V LVCMOS at P16
    	Info (169178): Pin io[13] uses I/O standard 3.3-V LVCMOS at P15
    	Info (169178): Pin io[14] uses I/O standard 3.3-V LVCMOS at L15
    	Info (169178): Pin io[15] uses I/O standard 3.3-V LVCMOS at R16
    	Info (169178): Pin io[16] uses I/O standard 3.3-V LVCMOS at K16
    	Info (169178): Pin io[17] uses I/O standard 3.3-V LVCMOS at L16
    	Info (169178): Pin io[18] uses I/O standard 3.3-V LVCMOS at N11
    	Info (169178): Pin io[19] uses I/O standard 3.3-V LVCMOS at N9
    	Info (169178): Pin io[20] uses I/O standard 3.3-V LVCMOS at P9
    	Info (169178): Pin io[21] uses I/O standard 3.3-V LVCMOS at N12
    	Info (169178): Pin io[22] uses I/O standard 3.3-V LVCMOS at R10
    	Info (169178): Pin io[23] uses I/O standard 3.3-V LVCMOS at P11
    	Info (169178): Pin io[24] uses I/O standard 3.3-V LVCMOS at R11
    	Info (169178): Pin io[25] uses I/O standard 3.3-V LVCMOS at T10
    	Info (169178): Pin io[26] uses I/O standard 3.3-V LVCMOS at T11
    	Info (169178): Pin io[27] uses I/O standard 3.3-V LVCMOS at R12
    	Info (169178): Pin io[28] uses I/O standard 3.3-V LVCMOS at T12
    	Info (169178): Pin io[29] uses I/O standard 3.3-V LVCMOS at R13
    	Info (169178): Pin io[30] uses I/O standard 3.3-V LVCMOS at B11
    	Info (169178): Pin io[31] uses I/O standard 3.3-V LVCMOS at E10
    	Info (169178): Pin inp_resn uses I/O standard 3.3-V LVCMOS at D9
    	Info (169178): Pin clock_50 uses I/O standard 3.3-V LVCMOS at R8
    
    Does anyone know how to remove any of these warnings ???
  • Cluso99Cluso99 Posts: 18,069
    edited 2015-05-06 21:09
    By adding these 3 lines
    set_global_assignment -name VERILOG_FILE dig.v
    set_global_assignment -name AHDL_FILE tim.tdf
    set_global_assignment -name AHDL_FILE top.tdf
    
    to the files
    BeMicroCV.qsf
    DE0-Nano.qsf
    DE2-115.qsf
    after these line(s)
    set_global_assignment -name FMAX_REQUIREMENT "80 MHz" -section_id clock_cog
    set_global_assignment -name FMAX_REQUIREMENT "160 MHz" -section_id clock_pll
    set_global_assignment -name VERILOG_MACRO "DISABLE_FONT_ROM=1"
    
    and the fix above, we are now down to 0/11 warnings without the need to add files to the project.
  • Cluso99Cluso99 Posts: 18,069
    edited 2015-06-03 21:49
    Today I tried to compile this clean(cleanest) install for the BeMicroCV.
    It took 16m33s - ugh!
    There were 6 errors and 17 warnings.
    2 errors complained about a missing BeMicroCV.sdc file and 4 errors were timing errors.

    Can I just copy the DE0-Nano.sdc file???

    Here are the errors and warnings
    Warning (19016): Clock multiplexers are found and protected
    	Warning (19017): Found clock multiplexer tim:clkgen|clk_pll~2
    Warning (113007): Byte addressed memory initialization file "hub_rom_low_b3.hex" was read in the word-addressed format
    Warning (113007): Byte addressed memory initialization file "hub_rom_low_b2.hex" was read in the word-addressed format
    Warning (113007): Byte addressed memory initialization file "hub_rom_low_b1.hex" was read in the word-addressed format
    Warning (113007): Byte addressed memory initialization file "hub_rom_low_b0.hex" was read in the word-addressed format
    Warning (113007): Byte addressed memory initialization file "hub_rom_high_unscrambled_b3.hex" was read in the word-addressed format
    Warning (113007): Byte addressed memory initialization file "hub_rom_high_unscrambled_b2.hex" was read in the word-addressed format
    Warning (113007): Byte addressed memory initialization file "hub_rom_high_unscrambled_b1.hex" was read in the word-addressed format
    Warning (113007): Byte addressed memory initialization file "hub_rom_high_unscrambled_b0.hex" was read in the word-addressed format
    Warning (13024): Output pins are stuck at VCC or GND
    	Warning (13410): Pin "ledg[1]" is stuck at GND
    	Warning (13410): Pin "ledg[2]" is stuck at GND
    	Warning (13410): Pin "ledg[3]" is stuck at GND
    	Warning (13410): Pin "ledg[4]" is stuck at GND
    	Warning (13410): Pin "ledg[5]" is stuck at GND
    	Warning (13410): Pin "ledg[6]" is stuck at GND
    	Warning (13410): Pin "ledg[7]" is stuck at GND
    Warning: RST port on the PLL is not properly connected on instance altpll:pll|altpll_0cp:auto_generated|generic_pll1. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock.
    	Info: Must be connected
    Warning: RST port on the PLL is not properly connected on instance altpll:pll|altpll_0cp:auto_generated|generic_pll1. The reset port on the PLL should be connected. If the PLL loses lock for any reason, you might need to manually reset the PLL in order to re-establish lock to the reference clock.
    	Info: Must be connected
    Warning (21300): LOCKED port on the PLL is not properly connected on instance "altpll:pll|altpll_0cp:auto_generated|generic_pll1". The LOCKED port on the PLL should be connected when the FBOUTCLK port is connected. Although it is unnecessary to connect the LOCKED signal, any logic driven off of an output clock of the PLL will not know when the PLL is locked and ready.
    Warning (292013): Feature LogicLock is only available with a valid subscription license. You can purchase a software subscription to gain full access to this feature.
    Warning (15714): Some pins have incomplete I/O assignments. Refer to the I/O Assignment Warnings report for details
    Warning (177007): PLL(s) placed in location FRACTIONALPLL_X54_Y38_N0 do not have a PLL clock to compensate specified - the Fitter will attempt to compensate all PLL clocks
    	Info (177008): PLL altpll:pll|altpll_0cp:auto_generated|generic_pll1~FRACTIONAL_PLL
    Critical Warning (332012): Synopsys Design Constraints File file not found: 'BeMicroCV.sdc'. A Synopsys Design Constraints File is required by the TimeQuest Timing Analyzer to get proper timing constraints. Without it, the Compiler will not properly optimize the design.
    Critical Warning (332012): Synopsys Design Constraints File file not found: 'BeMicroCV.sdc'. A Synopsys Design Constraints File is required by the TimeQuest Timing Analyzer to get proper timing constraints. Without it, the Compiler will not properly optimize the design.
    Critical Warning (332148): Timing requirements not met
    	Info (11105): For recommendations on closing timing, run Report Timing Closure Recommendations in the TimeQuest Timing Analyzer.
    Critical Warning (332148): Timing requirements not met
    	Info (11105): For recommendations on closing timing, run Report Timing Closure Recommendations in the TimeQuest Timing Analyzer.
    Critical Warning (332148): Timing requirements not met
    	Info (11105): For recommendations on closing timing, run Report Timing Closure Recommendations in the TimeQuest Timing Analyzer.
    Critical Warning (332148): Timing requirements not met
    	Info (11105): For recommendations on closing timing, run Report Timing Closure Recommendations in the TimeQuest Timing Analyzer.
    
  • SeairthSeairth Posts: 2,474
    edited 2015-06-04 05:21
    Cluso99 wrote: »
    Today I tried to compile this clean(cleanest) install for the BeMicroCV...

    2 errors complained about a missing BeMicroCV.sdc file and 4 errors were timing errors.

    Can I just copy the DE0-Nano.sdc file???

    Unfortunately, no. Cyclone IV and Cyclone V have very different PLL declarations.
  • LoopyBytelooseLoopyByteloose Posts: 12,537
    edited 2015-07-26 06:06
    Here is a link to an open source Verilog UART that uses a 50Mhz clock, 8N1 without flow control.

    It is not the fastest as it is both Rx and Tx, but it may be of use as it is a complete Verilog module with a  Github repository.

    http://opencores.org/project,osdvu

    And here is a link to another coder with explanation.
    http://www.fpga4fun.com/SerialInterface5.html

    And a TX only configuration.
    http://ece301.com/fpga-projects/52-uart-txd.html

    And a RX only configuration to mate with the above TX only
    http://ece301.com/fpga-projects/57-uart-rxd.html

    I haven't yet tried any as I am awaiting the arrival of my first FPGA devices.  But I also tend to feel that using a whole cog for serial i/o may be a bit wasteful.  These may allow one to get an 'outside' UART.
  • Anyone looking here for a clean Propeller 1v set of Verilog codes should go to Jac Goudsmit's BeMIcroCVA9 or visit his Github repository.

    He has done an excellent job of integrating the Verilog code for all the various Altera Development boards -- Terrasic or BeMIcro.

    https://github.com/jacgoudsmit/P1V

    thanks... jac
    You really seem to have mastered Quartus II and the P1V. We can all learn something from this repository.
  • Anyone looking here for a clean Propeller 1v set of Verilog codes should go to Jac Goudsmit's BeMIcroCVA9 or visit his Github repository.

    He has done an excellent job of integrating the Verilog code for all the various Altera Development boards -- Terrasic or BeMIcro.

    https://github.com/jacgoudsmit/P1V

    thanks... jac
    You really seem to have mastered Quartus II and the P1V. We can all learn something from this repository.

    Thanks for your kind words, but at this time I know barely enough of Verilog and Quartus to be dangerous. And I don't know hardly anything about the Xilinx ISE tools because I don't own any Xilinx hardware (yet).

    I don't know if a clean compile of P1V will ever be possible; Quartus is very picky (which is a good thing!) and it looks like it's simply impossible to do some things without generating warnings. And I could use any help I can get!

    ===Jac


  • Okay....
    Maybe not absolutely clean. But all the code that Parallax links to is older, and their .zip that includes the BeMicroCV doesn't work.

    You are still way ahead of me as I just got started with Quartus II, Verilog, and VHDL. At the very least, I don't have to bother with soldering to build something sophisticated.
  • Probably way off topic here, but a group of us all over the world are building retro CP/M, Z80, 6809 type computers on Cyclone IV boards, and we have just got a board working with four UARTs. It is using Quartus (version 13 to 15) and all compiles fine, and is VHDL. Old-skool stuff, with a UART component with a data bus, address bus, chip select, read and write pins.
    In the propeller world, you would build the uarts in cogs in software. But in the vhdl world, a uart is a component that is easy to drop into the code, and easy to add more with just a few lines of vhdl each time, so it makes more sense to add vhdl, and to keep cogs free for other more complex and flexible tasks.
    In the strange hybrid world of a propeller emulated on a fpga, well, anything goes, and it may well be better to add things in vhdl - eg SPI, vga drivers, external memory management units, external memory, and still have 8 cogs free.
Sign In or Register to comment.